Fix issue about GHashtable and GList
[platform/core/api/notification.git] / src / notification_internal.c
1 /*
2  * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <libintl.h>
23 #include <dbus/dbus.h>
24 #include <dbus/dbus-glib-lowlevel.h>
25 #include <gio/gio.h>
26
27 #include <app.h>
28 #include <app_control_internal.h>
29 #include <aul.h>
30 #include <appsvc.h>
31 #include <tizen.h>
32 #include <vconf-keys.h>
33 #include <vconf.h>
34
35 #include <notification.h>
36 #include <notification_list.h>
37 #include <notification_debug.h>
38 #include <notification_private.h>
39 #include <notification_noti.h>
40 #include <notification_ongoing.h>
41 #include <notification_group.h>
42 #include <notification_ipc.h>
43 #include <notification_internal.h>
44
45 typedef struct _notification_cb_info notification_cb_info_s;
46 typedef struct _notification_event_cb_info notification_event_cb_info_s;
47
48 typedef enum __notification_cb_type {
49         NOTIFICATION_CB_NORMAL = 1,
50         NOTIFICATION_CB_DETAILED,
51 } _notification_cb_type_e;
52
53 struct _notification_cb_info {
54         _notification_cb_type_e cb_type;
55         void (*changed_cb) (void *data, notification_type_e type);
56         void (*detailed_changed_cb) (void *data, notification_type_e type, notification_op *op_list, int num_op);
57         void *data;
58 };
59
60 struct _notification_event_cb_info {
61         int priv_id;
62         event_handler_cb cb;
63         void *userdata;
64 };
65
66 static GHashTable *_noti_cb_hash = NULL;
67 static GList *__noti_event_cb_list = NULL;
68
69 /* LCOV_EXCL_START */
70 static void __free_changed_cb_info(gpointer data)
71 {
72         notification_cb_info_s *noti_cb_info = (notification_cb_info_s *)data;
73         if (noti_cb_info)
74                 free(noti_cb_info);
75 }
76 /* LCOV_EXCL_STOP */
77
78 void notification_call_changed_cb_for_uid(notification_op *op_list, int op_num, uid_t uid)
79 {
80         notification_type_e type = 0;
81         GList *noti_cb_list = NULL;
82         notification_cb_info_s *noti_cb_info = NULL;
83
84         if (_noti_cb_hash == NULL)
85                 return;
86
87         noti_cb_list = (GList *)g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
88
89         if (noti_cb_list == NULL)
90                 return;
91
92         if (op_list == NULL) {
93                 NOTIFICATION_ERR("invalid data");
94                 return;
95         }
96
97         noti_cb_list = g_list_first(noti_cb_list);
98         notification_get_type(op_list->noti, &type);
99
100         for (; noti_cb_list != NULL; noti_cb_list = noti_cb_list->next) {
101                 noti_cb_info = noti_cb_list->data;
102
103                 if (noti_cb_info->cb_type == NOTIFICATION_CB_NORMAL && noti_cb_info->changed_cb) {
104                         noti_cb_info->changed_cb(noti_cb_info->data, type);
105                 }
106                 if (noti_cb_info->cb_type == NOTIFICATION_CB_DETAILED && noti_cb_info->detailed_changed_cb) {
107                         noti_cb_info->detailed_changed_cb(noti_cb_info->data,
108                                         type, op_list, op_num);
109                 }
110         }
111 }
112
113 static gint __priv_id_compare(gconstpointer a, gconstpointer b)
114 {
115         const notification_event_cb_info_s *info = NULL;
116
117         if (!a)
118                 return -1;
119
120         info = (notification_event_cb_info_s *)a;
121
122         if (info->priv_id == GPOINTER_TO_UINT(b))
123                 return 0;
124
125         return 1;
126 }
127
128 void notification_call_event_handler_cb(notification_h noti, int event_type)
129 {
130         int ret;
131         int priv_id;
132         GList *find_list;
133         notification_event_cb_info_s *info;
134
135         if (__noti_event_cb_list == NULL)
136                 return;
137
138         ret = notification_get_id(noti, NULL, &priv_id);
139         if (ret != NOTIFICATION_ERROR_NONE)
140                 return;
141
142         __noti_event_cb_list = g_list_first(__noti_event_cb_list);
143         find_list = g_list_find_custom(__noti_event_cb_list, GUINT_TO_POINTER(priv_id),
144                                        (GCompareFunc)__priv_id_compare);
145         if (find_list == NULL)
146                 return;
147
148         info = g_list_nth_data(find_list, 0);
149         info->cb(noti, event_type, info->userdata);
150 }
151
152 void notification_delete_event_handler_cb(int priv_id)
153 {
154         GList *delete_list;
155         notification_event_cb_info_s *info = NULL;
156
157         if (__noti_event_cb_list == NULL)
158                 return;
159
160         __noti_event_cb_list = g_list_first(__noti_event_cb_list);
161         delete_list = g_list_find_custom(__noti_event_cb_list, GUINT_TO_POINTER(priv_id),
162                                          (GCompareFunc)__priv_id_compare);
163
164         if (delete_list == NULL)
165                 return;
166
167         info = g_list_nth_data(delete_list, 0);
168         __noti_event_cb_list = g_list_remove(g_list_first(__noti_event_cb_list), info);
169
170         if (info)
171                 free(info);
172
173         if (__noti_event_cb_list == NULL)
174                 notification_ipc_event_monitor_fini();
175 }
176
177 EXPORT_API int notification_add_deferred_task(
178                 void (*deferred_task_cb)(void *data), void *user_data)
179 {
180         if (deferred_task_cb == NULL)
181                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
182
183         return notification_ipc_add_deffered_task(deferred_task_cb, user_data);
184 }
185
186 EXPORT_API int notification_del_deferred_task(
187                 void (*deferred_task_cb)(void *data))
188 {
189         if (deferred_task_cb == NULL)
190                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
191
192         return notification_ipc_del_deffered_task(deferred_task_cb);
193 }
194
195 EXPORT_API int notification_resister_changed_cb_for_uid(
196                 void (*changed_cb)(void *data, notification_type_e type),
197                 void *user_data, uid_t uid)
198 {
199         GList *noti_cb_list = NULL;
200         notification_cb_info_s *noti_cb_info_new = NULL;
201
202         if (changed_cb == NULL)
203                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
204
205         if (notification_ipc_monitor_init(uid) != NOTIFICATION_ERROR_NONE)
206                 return NOTIFICATION_ERROR_IO_ERROR;
207
208         if (_noti_cb_hash == NULL)
209                 _noti_cb_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
210
211         noti_cb_info_new = (notification_cb_info_s *)malloc(sizeof(notification_cb_info_s));
212         if (noti_cb_info_new == NULL) {
213                 NOTIFICATION_ERR("malloc failed");
214                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
215         }
216
217         noti_cb_info_new->cb_type = NOTIFICATION_CB_NORMAL;
218         noti_cb_info_new->changed_cb = changed_cb;
219         noti_cb_info_new->detailed_changed_cb = NULL;
220         noti_cb_info_new->data = user_data;
221
222         noti_cb_list = g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
223
224         if (noti_cb_list == NULL) {
225                 noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
226                 g_hash_table_insert(_noti_cb_hash, GUINT_TO_POINTER(uid), noti_cb_list);
227         } else {
228                 noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
229         }
230
231         return NOTIFICATION_ERROR_NONE;
232 }
233
234 EXPORT_API int notification_resister_changed_cb(
235                 void (*changed_cb)(void *data, notification_type_e type),
236                 void *user_data)
237 {
238         return notification_resister_changed_cb_for_uid(changed_cb, user_data, getuid());
239 }
240
241 static gint _noti_changed_compare(gconstpointer a, gconstpointer b)
242 {
243         const struct _notification_cb_info *info = NULL;
244
245         if (!a)
246                 return -1;
247         info = (notification_cb_info_s *)a;
248
249         if (info->changed_cb == b)
250                 return 0;
251
252         return 1;
253 }
254
255 EXPORT_API int notification_unresister_changed_cb_for_uid(
256                 void (*changed_cb)(void *data, notification_type_e type), uid_t uid)
257 {
258         notification_cb_info_s *noti_cb_info = NULL;
259         GList *noti_cb_list = NULL;
260         GList *delete_cb_list = NULL;
261
262         if (changed_cb == NULL)
263                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
264
265         if (_noti_cb_hash == NULL)
266                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
267
268         noti_cb_list = (GList *)g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
269
270         if (noti_cb_list == NULL)
271                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
272
273         noti_cb_list = g_list_first(noti_cb_list);
274         delete_cb_list = g_list_find_custom(noti_cb_list, (gconstpointer)changed_cb,
275                                               _noti_changed_compare);
276
277         if (delete_cb_list) {
278                 noti_cb_info = g_list_nth_data(delete_cb_list, 0);
279                 noti_cb_list = g_list_delete_link(noti_cb_list, delete_cb_list);
280                 __free_changed_cb_info(noti_cb_info);
281
282                 if (noti_cb_list == NULL) {
283                         g_hash_table_steal(_noti_cb_hash, GUINT_TO_POINTER(uid));
284                 } else {
285                         noti_cb_list = g_list_first(noti_cb_list);
286                         g_hash_table_replace(_noti_cb_hash, GUINT_TO_POINTER(uid), noti_cb_list);
287                 }
288
289         } else {
290                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
291         }
292
293         if (g_hash_table_size(_noti_cb_hash) == 0)
294                 notification_ipc_monitor_fini();
295
296         return NOTIFICATION_ERROR_NONE;
297 }
298
299 EXPORT_API int notification_unresister_changed_cb(
300                 void (*changed_cb)(void *data, notification_type_e type))
301 {
302         return notification_unresister_changed_cb_for_uid(changed_cb, getuid());
303 }
304
305 EXPORT_API int notification_update_progress(notification_h noti,
306                 int priv_id,
307                 double progress)
308 {
309         char *caller_pkgname = NULL;
310         int input_priv_id = 0;
311         int ret = 0;
312         double input_progress = 0.0;
313
314         if (priv_id <= NOTIFICATION_PRIV_ID_NONE) {
315                 if (noti == NULL)
316                         return NOTIFICATION_ERROR_INVALID_PARAMETER;
317                 else
318                         input_priv_id = noti->priv_id;
319
320         } else {
321                 input_priv_id = priv_id;
322         }
323
324         if (noti == NULL)
325                 caller_pkgname = notification_get_pkgname_by_pid();
326         else
327                 caller_pkgname = strdup(noti->caller_pkgname);
328
329         if (progress < 0.0)
330                 input_progress = 0.0;
331         else if (progress > 1.0)
332                 input_progress = 1.0;
333         else
334                 input_progress = progress;
335
336         ret = notification_ongoing_update_progress(caller_pkgname, input_priv_id,
337                         input_progress);
338
339         if (caller_pkgname)
340                 free(caller_pkgname);
341
342         return ret;
343 }
344
345 EXPORT_API int notification_update_size(notification_h noti,
346                 int priv_id,
347                 double size)
348 {
349         char *caller_pkgname = NULL;
350         int input_priv_id = 0;
351         int ret = 0;
352         double input_size = 0.0;
353
354         if (priv_id <= NOTIFICATION_PRIV_ID_NONE) {
355                 if (noti == NULL)
356                         return NOTIFICATION_ERROR_INVALID_PARAMETER;
357                 else
358                         input_priv_id = noti->priv_id;
359         } else {
360                 input_priv_id = priv_id;
361         }
362
363         if (noti == NULL)
364                 caller_pkgname = notification_get_pkgname_by_pid();
365         else
366                 caller_pkgname = strdup(noti->caller_pkgname);
367
368         if (size < 0.0)
369                 input_size = 0.0;
370         else
371                 input_size = size;
372
373         ret = notification_ongoing_update_size(caller_pkgname, input_priv_id,
374                         input_size);
375
376         if (caller_pkgname)
377                 free(caller_pkgname);
378
379         return ret;
380 }
381
382 EXPORT_API int notification_update_content(notification_h noti,
383                 int priv_id,
384                 const char *content)
385 {
386         char *caller_pkgname = NULL;
387         int input_priv_id = 0;
388         int ret = 0;
389
390         if (priv_id <= NOTIFICATION_PRIV_ID_NONE) {
391                 if (noti == NULL)
392                         return NOTIFICATION_ERROR_INVALID_PARAMETER;
393                 else
394                         input_priv_id = noti->priv_id;
395
396         } else {
397                 input_priv_id = priv_id;
398         }
399
400         if (noti == NULL)
401                 caller_pkgname = notification_get_pkgname_by_pid();
402         else
403                 caller_pkgname = strdup(noti->caller_pkgname);
404
405         ret = notification_ongoing_update_content(caller_pkgname, input_priv_id,
406                         content);
407
408         if (caller_pkgname)
409                 free(caller_pkgname);
410
411         return ret;
412 }
413
414 /* notification_set_icon will be removed */
415 /* LCOV_EXCL_START */
416 EXPORT_API int notification_set_icon(notification_h noti,
417                 const char *icon_path)
418 {
419         return notification_set_image(noti, NOTIFICATION_IMAGE_TYPE_ICON, icon_path);
420 }
421 /* LCOV_EXCL_STOP */
422
423 /* notification_get_icon will be removed */
424 /* LCOV_EXCL_START */
425 EXPORT_API int notification_get_icon(notification_h noti,
426                 char **icon_path)
427 {
428         int ret_err = NOTIFICATION_ERROR_NONE;
429         char *ret_image_path = NULL;
430
431         ret_err = notification_get_image(noti, NOTIFICATION_IMAGE_TYPE_ICON,
432                                 &ret_image_path);
433
434         if (ret_err == NOTIFICATION_ERROR_NONE && icon_path != NULL)
435                 *icon_path = ret_image_path;
436
437         return ret_err;
438 }
439 /* LCOV_EXCL_STOP */
440
441 EXPORT_API int notification_translate_localized_text(notification_h noti)
442 {
443         int noti_err = NOTIFICATION_ERROR_NONE;
444         char *ret_text = NULL;
445         char buf_key[32];
446         char *bundle_val = NULL;
447         char *new_text;
448         bundle *b;
449         notification_text_type_e type = NOTIFICATION_TEXT_TYPE_TITLE;
450
451         for (; type < NOTIFICATION_TEXT_TYPE_MAX; type++) {
452                 noti_err = notification_get_text(noti, type, &ret_text);
453                 if (noti_err == NOTIFICATION_ERROR_NONE && ret_text) {
454                         if (noti->b_text == NULL) {
455                                 noti->b_text = bundle_create();
456                                 if (noti->b_text == NULL)
457                                         return NOTIFICATION_ERROR_OUT_OF_MEMORY;
458                         }
459
460                         b = noti->b_text;
461
462                         new_text = strdup(ret_text);
463
464                         snprintf(buf_key, sizeof(buf_key), "%d", type);
465                         bundle_get_str(b, buf_key, &bundle_val);
466                         if (bundle_val != NULL)
467                                 bundle_del(b, buf_key);
468
469                         bundle_add_str(b, buf_key, new_text);
470                         free(new_text);
471                         new_text = NULL;
472
473                         noti->num_format_args = 0;
474                         bundle_val = NULL;
475                 }
476         }
477
478         return noti_err;
479 }
480
481 /* LCOV_EXCL_START */
482 EXPORT_API int notification_set_title(notification_h noti,
483                 const char *title,
484                 const char *loc_title)
485 {
486         return notification_set_text(noti, NOTIFICATION_TEXT_TYPE_TITLE,
487                                 title, loc_title,
488                                 NOTIFICATION_VARIABLE_TYPE_NONE);;
489 }
490 /* LCOV_EXCL_STOP */
491
492 /* LCOV_EXCL_START */
493 EXPORT_API int notification_get_title(notification_h noti,
494                 char **title,
495                 char **loc_title)
496 {
497         int noti_err = NOTIFICATION_ERROR_NONE;
498         char *ret_text = NULL;
499
500         noti_err = notification_get_text(noti, NOTIFICATION_TEXT_TYPE_TITLE,
501                                 &ret_text);
502
503         if (title != NULL)
504                 *title = ret_text;
505
506         if (loc_title != NULL)
507                 *loc_title = NULL;
508
509         return noti_err;
510 }
511 /* LCOV_EXCL_STOP */
512
513 /* LCOV_EXCL_START */
514 EXPORT_API int notification_set_content(notification_h noti,
515                 const char *content,
516                 const char *loc_content)
517 {
518         return notification_set_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT,
519                                 content, loc_content,
520                                 NOTIFICATION_VARIABLE_TYPE_NONE);
521 }
522 /* LCOV_EXCL_STOP */
523
524 /* LCOV_EXCL_START */
525 EXPORT_API int notification_get_content(notification_h noti,
526                 char **content,
527                 char **loc_content)
528 {
529         int noti_err = NOTIFICATION_ERROR_NONE;
530         char *ret_text = NULL;
531
532         noti_err = notification_get_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT,
533                                 &ret_text);
534
535         if (content != NULL)
536                 *content = ret_text;
537
538         if (loc_content != NULL)
539                 *loc_content = NULL;
540
541         return noti_err;
542 }
543 /* LCOV_EXCL_STOP */
544
545 /* LCOV_EXCL_START */
546 EXPORT_API int notification_set_application(notification_h noti,
547                 const char *pkgname)
548 {
549         if (noti == NULL || pkgname == NULL)
550                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
551
552         if (noti->launch_pkgname)
553                 free(noti->launch_pkgname);
554
555         noti->launch_pkgname = strdup(pkgname);
556
557         return NOTIFICATION_ERROR_NONE;
558 }
559 /* LCOV_EXCL_STOP */
560
561 /* LCOV_EXCL_START */
562 EXPORT_API int notification_get_application(notification_h noti,
563                 char **pkgname)
564 {
565         if (noti == NULL || pkgname == NULL)
566                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
567
568         if (noti->launch_pkgname)
569                 *pkgname = noti->launch_pkgname;
570         else
571                 *pkgname = noti->caller_pkgname;
572
573         return NOTIFICATION_ERROR_NONE;
574 }
575 /* LCOV_EXCL_STOP */
576
577 /* LCOV_EXCL_START */
578 EXPORT_API int notification_set_args(notification_h noti, bundle *args,
579                 bundle *group_args)
580 {
581         if (noti == NULL || args == NULL)
582                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
583
584         if (noti->args)
585                 bundle_free(noti->args);
586
587         noti->args = bundle_dup(args);
588
589         if (noti->group_args) {
590                 bundle_free(noti->group_args);
591                 noti->group_args = NULL;
592         }
593
594         if (group_args != NULL)
595                 noti->group_args = bundle_dup(group_args);
596
597         return NOTIFICATION_ERROR_NONE;
598 }
599 /* LCOV_EXCL_STOP */
600
601 /* LCOV_EXCL_START */
602 EXPORT_API int notification_get_args(notification_h noti,
603                 bundle **args,
604                 bundle **group_args)
605 {
606         if (noti == NULL || args == NULL)
607                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
608
609         if (noti->args)
610                 *args = noti->args;
611         else
612                 *args = NULL;
613
614         if (group_args != NULL && noti->group_args)
615                 *group_args = noti->group_args;
616
617         return NOTIFICATION_ERROR_NONE;
618 }
619 /* LCOV_EXCL_STOP */
620
621 /* LCOV_EXCL_START */
622 int notification_get_grouping_list_for_uid(notification_type_e type, int count,
623                 notification_list_h *list, uid_t uid)
624 {
625         notification_list_h get_list = NULL;
626         int ret = 0;
627
628         if (list == NULL)
629                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
630
631         ret = notification_noti_get_grouping_list(type, count, &get_list, uid);
632         if (ret != NOTIFICATION_ERROR_NONE)
633                 return ret;
634
635         *list = get_list;
636
637         return NOTIFICATION_ERROR_NONE;
638 }
639
640 EXPORT_API int notification_get_grouping_list(notification_type_e type, int count,
641                 notification_list_h *list)
642 {
643         return notification_get_grouping_list_for_uid(type, count, list, getuid());
644 }
645 /* LCOV_EXCL_STOP */
646
647 /* LCOV_EXCL_START */
648 EXPORT_API int notification_delete_group_by_group_id(const char *pkgname,
649                 notification_type_e type,
650                 int group_id)
651 {
652         int ret = 0;
653         char *caller_pkgname = NULL;
654
655         if (pkgname == NULL)
656                 caller_pkgname = notification_get_pkgname_by_pid();
657         else
658                 caller_pkgname = strdup(pkgname);
659
660         ret = notification_ipc_request_delete_multiple(type, caller_pkgname, getuid());
661
662         if (caller_pkgname)
663                 free(caller_pkgname);
664
665         return ret;
666 }
667 /* LCOV_EXCL_STOP */
668
669 /* LCOV_EXCL_START */
670 int notification_delete_group_by_priv_id_for_uid(const char *pkgname,
671                 notification_type_e type,
672                 int priv_id, uid_t uid)
673 {
674         int ret = 0;
675         char *caller_pkgname = NULL;
676
677         if (pkgname == NULL)
678                 caller_pkgname = notification_get_pkgname_by_pid();
679         else
680                 caller_pkgname = strdup(pkgname);
681
682         ret = notification_ipc_request_delete_single(type, caller_pkgname, priv_id, uid);
683
684         if (caller_pkgname)
685                 free(caller_pkgname);
686
687         return ret;
688 }
689 /* LCOV_EXCL_STOP */
690
691 /* LCOV_EXCL_START */
692 EXPORT_API int notification_delete_group_by_priv_id(const char *pkgname,
693                 notification_type_e type,
694                 int priv_id)
695 {
696         return notification_delete_group_by_priv_id_for_uid(pkgname, type, priv_id, getuid());
697 }
698
699 int notification_get_count_for_uid(notification_type_e type,
700                 const char *pkgname,
701                 int group_id,
702                 int priv_id, int *count,
703                 uid_t uid)
704 {
705         int ret = 0;
706         char *caller_pkgname = NULL;
707
708         if (count == NULL)
709                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
710
711         if (pkgname == NULL)
712                 caller_pkgname = notification_get_pkgname_by_pid();
713         else
714                 caller_pkgname = strdup(pkgname);
715
716         ret = notification_ipc_request_get_count(
717                         type,
718                         caller_pkgname,
719                         group_id,
720                         priv_id,
721                         count,
722                         uid);
723
724         if (caller_pkgname)
725                 free(caller_pkgname);
726
727         return ret;
728 }
729 /* LCOV_EXCL_STOP */
730
731 /* LCOV_EXCL_START */
732 EXPORT_API int notification_get_count(notification_type_e type,
733                 const char *pkgname,
734                 int group_id,
735                 int priv_id, int *count)
736 {
737         return notification_get_count_for_uid(type, pkgname, group_id, priv_id, count, getuid());
738 }
739
740 int notification_clear_for_uid(notification_type_e type, uid_t uid)
741 {
742         if (type <= NOTIFICATION_TYPE_NONE || type >= NOTIFICATION_TYPE_MAX)
743                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
744
745         return notification_ipc_request_delete_multiple(type, NULL, uid);
746 }
747 /* LCOV_EXCL_STOP */
748
749 /* LCOV_EXCL_START */
750 EXPORT_API int notification_clear(notification_type_e type)
751 {
752         return notification_clear_for_uid(type, getuid());
753 }
754
755 EXPORT_API int notification_op_get_data(notification_op *noti_op, notification_op_data_type_e type,
756                 void *data)
757 {
758         if (noti_op == NULL || data == NULL)
759                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
760
761         switch (type) {
762         case NOTIFICATION_OP_DATA_TYPE:
763                 *((int *)data) = noti_op->type;
764                 break;
765         case NOTIFICATION_OP_DATA_PRIV_ID:
766                 *((int *)data) = noti_op->priv_id;
767                 break;
768         case NOTIFICATION_OP_DATA_NOTI:
769                 *((notification_h *)data) = noti_op->noti;
770                 break;
771         case NOTIFICATION_OP_DATA_EXTRA_INFO_1:
772                 *((int *)data) = noti_op->extra_info_1;
773                 break;
774         case NOTIFICATION_OP_DATA_EXTRA_INFO_2:
775                 *((int *)data) = noti_op->extra_info_2;
776                 break;
777         default:
778                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
779                 break;
780         }
781
782         return NOTIFICATION_ERROR_NONE;
783 }
784 /* LCOV_EXCL_STOP */
785
786 /* LCOV_EXCL_START */
787 EXPORT_API int notification_set_pkgname(notification_h noti,
788                 const char *pkgname)
789 {
790         if (noti == NULL || pkgname == NULL)
791                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
792
793         /* Remove previous caller pkgname */
794         if (noti->caller_pkgname) {
795                 free(noti->caller_pkgname);
796                 noti->caller_pkgname = NULL;
797         }
798
799         noti->caller_pkgname = strdup(pkgname);
800
801         return NOTIFICATION_ERROR_NONE;
802 }
803 /* LCOV_EXCL_STOP */
804
805 /* LCOV_EXCL_START */
806 int notification_delete_all_by_type_for_uid(const char *pkgname,
807                 notification_type_e type, uid_t uid)
808 {
809         int ret = 0;
810         char *caller_pkgname = NULL;
811
812         if (type <= NOTIFICATION_TYPE_NONE || type >= NOTIFICATION_TYPE_MAX)
813                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
814
815         if (pkgname == NULL)
816                 caller_pkgname = notification_get_pkgname_by_pid();
817         else
818                 caller_pkgname = strdup(pkgname);
819
820         ret = notification_ipc_request_delete_multiple(type, caller_pkgname, uid);
821
822         if (caller_pkgname)
823                 free(caller_pkgname);
824
825         return ret;
826 }
827 /* LCOV_EXCL_STOP */
828
829 /* LCOV_EXCL_START */
830 EXPORT_API int notification_delete_all_by_type(const char *pkgname,
831                 notification_type_e type)
832 {
833         return notification_delete_all_by_type_for_uid(pkgname, type, getuid());
834 }
835
836 int notification_delete_by_priv_id_for_uid(const char *pkgname,
837                 notification_type_e type,
838                 int priv_id,
839                 uid_t uid)
840 {
841         int ret = 0;
842         char *caller_pkgname = NULL;
843
844         if (priv_id <= NOTIFICATION_PRIV_ID_NONE)
845                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
846
847         if (pkgname == NULL)
848                 caller_pkgname = notification_get_pkgname_by_pid();
849         else
850                 caller_pkgname = strdup(pkgname);
851
852         ret = notification_ipc_request_delete_single(type, caller_pkgname, priv_id, uid);
853
854         if (caller_pkgname)
855                 free(caller_pkgname);
856
857         return ret;
858 }
859 /* LCOV_EXCL_STOP */
860
861 /* LCOV_EXCL_START */
862 EXPORT_API int notification_delete_by_priv_id(const char *pkgname,
863                 notification_type_e type,
864                 int priv_id)
865 {
866         return notification_delete_by_priv_id_for_uid(pkgname, type, priv_id, getuid());
867 }
868
869 EXPORT_API int notification_set_execute_option(notification_h noti,
870                 notification_execute_type_e type,
871                 const char *text,
872                 const char *key,
873                 bundle *service_handle)
874 {
875         char buf_key[32] = { 0, };
876         char *ret_val = NULL;
877         bundle *b = NULL;
878
879         if (noti == NULL)
880                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
881
882         if (type <= NOTIFICATION_EXECUTE_TYPE_NONE
883                         || type >= NOTIFICATION_EXECUTE_TYPE_MAX)
884                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
885
886         if (noti->b_execute_option == NULL)
887                 noti->b_execute_option = bundle_create();
888
889         b = noti->b_execute_option;
890
891         if (text != NULL) {
892                 snprintf(buf_key, sizeof(buf_key), "text%d", type);
893
894                 bundle_get_str(b, buf_key, &ret_val);
895                 if (ret_val != NULL)
896                         bundle_del(b, buf_key);
897
898                 bundle_add_str(b, buf_key, text);
899         }
900
901         if (key != NULL) {
902                 snprintf(buf_key, sizeof(buf_key), "key%d", type);
903
904                 bundle_get_str(b, buf_key, &ret_val);
905                 if (ret_val != NULL)
906                         bundle_del(b, buf_key);
907
908                 bundle_add_str(b, buf_key, key);
909         }
910
911         switch ((int)type) {
912         case NOTIFICATION_EXECUTE_TYPE_RESPONDING:
913                 if (noti->b_service_responding != NULL) {
914                         bundle_free(noti->b_service_responding);
915                         noti->b_service_responding = NULL;
916                 }
917
918                 if (service_handle != NULL)
919                         noti->b_service_responding = bundle_dup(service_handle);
920
921                 break;
922         case NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH:
923                 if (noti->b_service_single_launch != NULL) {
924                         bundle_free(noti->b_service_single_launch);
925                         noti->b_service_single_launch = NULL;
926                 }
927
928                 if (service_handle != NULL)
929                         noti->b_service_single_launch =
930                                 bundle_dup(service_handle);
931
932                 break;
933         case NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH:
934                 if (noti->b_service_multi_launch != NULL) {
935                         bundle_free(noti->b_service_multi_launch);
936                         noti->b_service_multi_launch = NULL;
937                 }
938
939                 if (service_handle != NULL)
940                         noti->b_service_multi_launch =
941                                 bundle_dup(service_handle);
942
943                 break;
944         }
945
946         return NOTIFICATION_ERROR_NONE;
947 }
948 /* LCOV_EXCL_STOP */
949
950 /* LCOV_EXCL_START */
951 EXPORT_API int notification_get_id(notification_h noti,
952                 int *group_id, int *priv_id)
953 {
954         if (noti == NULL)
955                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
956
957         if (group_id) {
958                 if (noti->group_id < NOTIFICATION_GROUP_ID_NONE)
959                         *group_id = NOTIFICATION_GROUP_ID_NONE;
960                 else
961                         *group_id = noti->group_id;
962         }
963
964         if (priv_id)
965                 *priv_id = noti->priv_id;
966
967         return NOTIFICATION_ERROR_NONE;
968 }
969 /* LCOV_EXCL_STOP */
970
971 /* LCOV_EXCL_START */
972 notification_h notification_load_for_uid(char *pkgname,
973                 int priv_id, uid_t uid)
974 {
975         int ret = 0;
976         notification_h noti = NULL;
977
978         noti = (notification_h)calloc(1, sizeof(struct _notification));
979         if (noti == NULL) {
980                 NOTIFICATION_ERR("NO MEMORY : noti == NULL");
981                 return NULL;
982         }
983
984         ret = notification_ipc_request_load_noti_by_priv_id(noti, pkgname, priv_id, uid);
985         if (ret != NOTIFICATION_ERROR_NONE) {
986                 notification_free(noti);
987                 return NULL;
988         }
989
990         return noti;
991 }
992 /* LCOV_EXCL_STOP */
993
994 /* LCOV_EXCL_START */
995 EXPORT_API notification_h notification_load(char *pkgname,
996                 int priv_id)
997 {
998         return notification_load_for_uid(pkgname, priv_id, getuid());
999 }
1000 /* LCOV_EXCL_STOP */
1001
1002 /* LCOV_EXCL_START */
1003 EXPORT_API notification_h notification_new(notification_type_e type,
1004                 int group_id, int priv_id)
1005 {
1006         return notification_create(type);
1007 }
1008
1009 static void _notification_get_text_domain(notification_h noti)
1010 {
1011 }
1012 /* LCOV_EXCL_STOP */
1013
1014 /* LCOV_EXCL_START */
1015 EXPORT_API int notification_get_execute_option(notification_h noti,
1016                 notification_execute_type_e type,
1017                 const char **text,
1018                 bundle **service_handle)
1019 {
1020         char buf_key[32] = { 0, };
1021         char *ret_val = NULL;
1022         char *get_str = NULL;
1023         bundle *b = NULL;
1024
1025         if (noti == NULL)
1026                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1027
1028         if (type <= NOTIFICATION_EXECUTE_TYPE_NONE
1029                         || type >= NOTIFICATION_EXECUTE_TYPE_MAX)
1030                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1031
1032
1033         switch (type) {
1034         case NOTIFICATION_EXECUTE_TYPE_RESPONDING:
1035                 b = noti->b_service_responding;
1036                 break;
1037         case NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH:
1038                 b = noti->b_service_single_launch;
1039                 break;
1040         case NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH:
1041                 b = noti->b_service_multi_launch;
1042                 break;
1043         default:
1044                 break;
1045         }
1046
1047         if (b != NULL) {
1048                 if (text != NULL) {
1049                         if (noti->domain == NULL || noti->dir == NULL)
1050                                 _notification_get_text_domain(noti);
1051
1052                         snprintf(buf_key, sizeof(buf_key), "key%d", type);
1053
1054                         bundle_get_str(b, buf_key, &ret_val);
1055                         if (ret_val != NULL && noti->domain != NULL
1056                                         && noti->dir != NULL) {
1057                                 bindtextdomain(noti->domain, noti->dir);
1058
1059                                 get_str = dgettext(noti->domain, ret_val);
1060
1061                                 *text = get_str;
1062                         } else if (ret_val != NULL) {
1063                                 get_str = dgettext("sys_string", ret_val);
1064
1065                                 *text = get_str;
1066                         } else {
1067                                 snprintf(buf_key, sizeof(buf_key), "text%d",
1068                                                 type);
1069
1070                                 bundle_get_str(b, buf_key, &ret_val);
1071
1072                                 *text = ret_val;
1073                         }
1074                 }
1075         }
1076
1077         if (service_handle != NULL)
1078                 *service_handle = b;
1079
1080         return NOTIFICATION_ERROR_NONE;
1081 }
1082 /* LCOV_EXCL_STOP */
1083
1084 EXPORT_API int notification_insert_for_uid(notification_h noti,
1085                 int *priv_id, uid_t uid)
1086 {
1087         int ret = 0;
1088         int id = 0;
1089
1090         if (noti == NULL)
1091                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1092
1093         if (noti->type <= NOTIFICATION_TYPE_NONE
1094                         || noti->type >= NOTIFICATION_TYPE_MAX)
1095                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1096
1097         noti->uid = uid;
1098         noti->insert_time = time(NULL);
1099
1100         ret = notification_ipc_request_insert(noti, &id);
1101         if (ret != NOTIFICATION_ERROR_NONE)
1102                 return ret;
1103
1104         noti->priv_id = id;
1105         NOTIFICATION_DBG("from master:%d", id);
1106
1107         /* If priv_id is valid data, set priv_id */
1108         if (priv_id != NULL)
1109                 *priv_id = noti->priv_id;
1110
1111         return NOTIFICATION_ERROR_NONE;
1112 }
1113
1114 EXPORT_API int notification_insert(notification_h noti,
1115                 int *priv_id)
1116 {
1117         return notification_insert_for_uid(noti, priv_id, getuid());
1118 }
1119
1120 EXPORT_API int notification_update_async_for_uid(notification_h noti,
1121                 void (*result_cb)(int priv_id, int result, void *data), void *user_data, uid_t uid)
1122 {
1123         if (noti == NULL)
1124                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1125
1126         noti->uid = uid;
1127         /* Update insert time ? */
1128         noti->insert_time = time(NULL);
1129
1130         return notification_ipc_request_update_async(noti, result_cb, user_data);
1131 }
1132
1133 EXPORT_API int notification_update_async(notification_h noti,
1134                 void (*result_cb)(int priv_id, int result, void *data), void *user_data)
1135 {
1136         return notification_update_async_for_uid(noti, result_cb, user_data, getuid());
1137 }
1138
1139 EXPORT_API int notification_register_detailed_changed_cb_for_uid(
1140                 void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
1141                 void *user_data, uid_t uid)
1142 {
1143         GList *noti_cb_list = NULL;
1144         notification_cb_info_s *noti_cb_info_new = NULL;
1145
1146         if (detailed_changed_cb == NULL)
1147                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1148
1149         if (notification_ipc_monitor_init(uid) != NOTIFICATION_ERROR_NONE)
1150                 return NOTIFICATION_ERROR_IO_ERROR;
1151
1152         if (_noti_cb_hash == NULL)
1153                 _noti_cb_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
1154
1155         noti_cb_info_new = (notification_cb_info_s *)malloc(sizeof(notification_cb_info_s));
1156         if (noti_cb_info_new == NULL) {
1157                 NOTIFICATION_ERR("malloc failed");
1158                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1159         }
1160
1161         noti_cb_info_new->cb_type = NOTIFICATION_CB_DETAILED;
1162         noti_cb_info_new->changed_cb = NULL;
1163         noti_cb_info_new->detailed_changed_cb = detailed_changed_cb;
1164         noti_cb_info_new->data = user_data;
1165
1166         noti_cb_list = g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
1167
1168         if (noti_cb_list == NULL) {
1169                 noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
1170                 g_hash_table_insert(_noti_cb_hash, GUINT_TO_POINTER(uid), noti_cb_list);
1171         } else {
1172                 noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
1173         }
1174
1175         return NOTIFICATION_ERROR_NONE;
1176 }
1177
1178 EXPORT_API int notification_register_detailed_changed_cb(
1179                 void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
1180                 void *user_data)
1181 {
1182         return notification_register_detailed_changed_cb_for_uid(detailed_changed_cb, user_data, getuid());
1183 }
1184
1185 static gint _noti_detailed_changed_compare(gconstpointer a, gconstpointer b)
1186 {
1187         const struct _notification_cb_info *info = NULL;
1188
1189         if (!a)
1190                 return -1;
1191         info = (notification_cb_info_s *)a;
1192
1193         if (info->detailed_changed_cb == b)
1194                 return 0;
1195
1196         return 1;
1197 }
1198
1199 EXPORT_API int notification_unregister_detailed_changed_cb_for_uid(
1200                 void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
1201                 void *user_data, uid_t uid)
1202 {
1203         notification_cb_info_s *noti_cb_info = NULL;
1204         GList *noti_cb_list = NULL;
1205         GList *delete_cb_list = NULL;
1206
1207         if (detailed_changed_cb == NULL)
1208                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1209
1210         if (_noti_cb_hash == NULL)
1211                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1212
1213         noti_cb_list = (GList *)g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
1214
1215         if (noti_cb_list == NULL)
1216                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1217
1218         noti_cb_list = g_list_first(noti_cb_list);
1219         delete_cb_list = g_list_find_custom(noti_cb_list, (gconstpointer)detailed_changed_cb,
1220                                             _noti_detailed_changed_compare);
1221
1222         if (delete_cb_list) {
1223                 noti_cb_info = (notification_cb_info_s *)g_list_nth_data(delete_cb_list, 0);
1224                 noti_cb_list = g_list_delete_link(noti_cb_list, delete_cb_list);
1225                 __free_changed_cb_info(noti_cb_info);
1226                 if (noti_cb_list == NULL) {
1227                         g_hash_table_steal(_noti_cb_hash, GUINT_TO_POINTER(uid));
1228                 } else {
1229                         noti_cb_list = g_list_first(noti_cb_list);
1230                         g_hash_table_replace(_noti_cb_hash, GUINT_TO_POINTER(uid), noti_cb_list);
1231                 }
1232
1233         } else {
1234                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1235         }
1236
1237         if (g_hash_table_size(_noti_cb_hash) == 0)
1238                 notification_ipc_monitor_fini();
1239
1240         return NOTIFICATION_ERROR_NONE;
1241
1242 }
1243
1244 EXPORT_API int notification_unregister_detailed_changed_cb(
1245                 void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
1246                 void *user_data)
1247 {
1248         return notification_unregister_detailed_changed_cb_for_uid(detailed_changed_cb, user_data, getuid());
1249 }
1250
1251 /* LCOV_EXCL_START */
1252 EXPORT_API int notification_is_service_ready(void)
1253 {
1254         return notification_ipc_is_master_ready();
1255 }
1256 /* LCOV_EXCL_STOP */
1257
1258 EXPORT_API int notification_set_uid(notification_h noti,
1259                 uid_t uid)
1260 {
1261         if (noti == NULL)
1262                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1263
1264         noti->uid = uid;
1265         return NOTIFICATION_ERROR_NONE;
1266 }
1267
1268 EXPORT_API int notification_get_uid(notification_h noti,
1269                 uid_t *uid)
1270 {
1271         if (noti == NULL || uid == NULL)
1272                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1273
1274         *uid = noti->uid;
1275         return NOTIFICATION_ERROR_NONE;
1276 }
1277
1278 EXPORT_API int notification_post_for_uid(notification_h noti, uid_t uid)
1279 {
1280         int ret = 0;
1281         int id = 0;
1282
1283         if (noti == NULL)
1284                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1285
1286         if (noti->type <= NOTIFICATION_TYPE_NONE
1287                         || noti->type >= NOTIFICATION_TYPE_MAX)
1288                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1289
1290         /* Save insert time */
1291         noti->insert_time = time(NULL);
1292         noti->uid = uid;
1293
1294         ret = notification_ipc_request_insert(noti, &id);
1295         if (ret != NOTIFICATION_ERROR_NONE)
1296                 return ret;
1297
1298         noti->priv_id = id;
1299         NOTIFICATION_DBG("from master:%d", id);
1300
1301         return NOTIFICATION_ERROR_NONE;
1302 }
1303
1304 EXPORT_API int notification_update_for_uid(notification_h noti, uid_t uid)
1305 {
1306         if (noti == NULL) {
1307                 notification_ipc_request_refresh(uid);
1308                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1309         }
1310
1311         noti->uid = uid;
1312         /* Update insert time ? */
1313         noti->insert_time = time(NULL);
1314
1315         return notification_ipc_request_update(noti);
1316 }
1317
1318 EXPORT_API int notification_delete_for_uid(notification_h noti, uid_t uid)
1319 {
1320
1321         if (noti == NULL)
1322                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1323
1324         return notification_ipc_request_delete_single(NOTIFICATION_TYPE_NONE,
1325                                 noti->caller_pkgname, noti->priv_id, uid);
1326 }
1327
1328 EXPORT_API int notification_delete_all_for_uid(notification_type_e type, uid_t uid)
1329 {
1330         int ret = 0;
1331         char *caller_pkgname = NULL;
1332
1333         if (type <= NOTIFICATION_TYPE_NONE || type >= NOTIFICATION_TYPE_MAX)
1334                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1335
1336         caller_pkgname = notification_get_pkgname_by_pid();
1337
1338         ret = notification_ipc_request_delete_multiple(type, caller_pkgname, uid);
1339
1340         if (caller_pkgname)
1341                 free(caller_pkgname);
1342
1343         return ret;
1344 }
1345
1346 EXPORT_API notification_h notification_load_by_tag_for_uid(const char *tag, uid_t uid)
1347 {
1348         int ret = 0;
1349         notification_h noti = NULL;
1350         char *caller_pkgname = NULL;
1351
1352         if (tag == NULL) {
1353                 NOTIFICATION_ERR("Invalid parameter");
1354                 set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
1355                 return NULL;
1356         }
1357
1358         caller_pkgname = notification_get_pkgname_by_pid();
1359         if (!caller_pkgname) {
1360                 /* LCOV_EXCL_START */
1361                 NOTIFICATION_ERR("Failed to get a package name");
1362                 set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
1363                 return NULL;
1364                 /* LCOV_EXCL_STOP */
1365         }
1366
1367         noti = (notification_h)calloc(1, sizeof(struct _notification));
1368         if (noti == NULL) {
1369                 /* LCOV_EXCL_START */
1370                 NOTIFICATION_ERR("Failed to alloc a new notification");
1371                 set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
1372                 free(caller_pkgname);
1373
1374                 return NULL;
1375                 /* LCOV_EXCL_STOP */
1376         }
1377
1378         ret = notification_ipc_request_load_noti_by_tag(noti, caller_pkgname, (char *)tag, uid);
1379         free(caller_pkgname);
1380
1381         set_last_result(ret);
1382         if (ret != NOTIFICATION_ERROR_NONE) {
1383                 notification_free(noti);
1384                 return NULL;
1385         }
1386
1387         return noti;
1388 }
1389
1390 EXPORT_API notification_h notification_create_from_package_template(const char *pkgname, const char *template_name)
1391 {
1392         int ret = 0;
1393         notification_h noti = NULL;
1394
1395         if (pkgname == NULL || template_name == NULL) {
1396                 NOTIFICATION_ERR("Invalid parameter");
1397                 set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
1398                 return NULL;
1399         }
1400
1401         noti = (notification_h)calloc(1, sizeof(struct _notification));
1402         if (noti == NULL) {
1403                 NOTIFICATION_ERR("Failed to alloc a new notification");
1404                 set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
1405                 return NULL;
1406         }
1407
1408         ret = notification_ipc_request_create_from_package_template(noti, pkgname, template_name);
1409
1410         set_last_result(ret);
1411         if (ret != NOTIFICATION_ERROR_NONE) {
1412                 notification_free(noti);
1413                 return NULL;
1414         }
1415
1416         return noti;
1417 }
1418
1419 EXPORT_API int notification_set_default_button(notification_h noti, notification_button_index_e index)
1420 {
1421         if (noti == NULL)
1422                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1423
1424         if (index < 0 || index > NOTIFICATION_BUTTON_6)
1425                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1426
1427         noti->default_button_index = index;
1428
1429         return NOTIFICATION_ERROR_NONE;
1430 }
1431
1432 EXPORT_API int notification_get_default_button(notification_h noti, notification_button_index_e *index)
1433 {
1434         if (noti == NULL || index == NULL)
1435                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1436
1437         *index = noti->default_button_index;
1438
1439         return NOTIFICATION_ERROR_NONE;
1440 }
1441
1442 EXPORT_API int notification_get_ongoing_value_type(notification_h noti, notification_ongoing_value_type_e *type)
1443 {
1444         if (noti == NULL || type == NULL)
1445                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1446
1447         *type = noti->ongoing_value_type;
1448
1449         return NOTIFICATION_ERROR_NONE;
1450 }
1451
1452 EXPORT_API int notification_set_ongoing_value_type(notification_h noti, notification_ongoing_value_type_e type)
1453 {
1454         if (noti == NULL)
1455                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1456
1457         if (type < NOTIFICATION_ONGOING_VALUE_TYPE_PERCENT || type > NOTIFICATION_ONGOING_VALUE_TYPE_TIME)
1458                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1459
1460         noti->ongoing_value_type = type;
1461
1462         return NOTIFICATION_ERROR_NONE;
1463 }
1464
1465 EXPORT_API int notification_get_ongoing_time(notification_h noti, int *current, int *duration)
1466 {
1467         if (noti == NULL || current == NULL || duration == NULL)
1468                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1469
1470         *current = noti->ongoing_current;
1471         *duration = noti->ongoing_duration;
1472
1473         return NOTIFICATION_ERROR_NONE;
1474 }
1475
1476 EXPORT_API int notification_set_ongoing_time(notification_h noti, int current, int duration)
1477 {
1478         if (noti == NULL)
1479                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1480
1481         if (current < 0 || duration < 0 || current > duration)
1482                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1483
1484         noti->ongoing_current = current;
1485         noti->ongoing_duration = duration;
1486
1487         return NOTIFICATION_ERROR_NONE;
1488 }
1489
1490 EXPORT_API int notification_get_hide_timeout(notification_h noti, int *timeout)
1491 {
1492         if (noti == NULL || timeout == NULL)
1493                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1494
1495         *timeout = noti->timeout;
1496
1497         return NOTIFICATION_ERROR_NONE;
1498 }
1499
1500 EXPORT_API int notification_set_hide_timeout(notification_h noti, int timeout)
1501 {
1502         if (noti == NULL || timeout < 0)
1503                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1504
1505         noti->timeout = timeout;
1506
1507         return NOTIFICATION_ERROR_NONE;
1508 }
1509
1510 EXPORT_API int notification_get_text_input_max_length(notification_h noti, int *text_input_max_length)
1511 {
1512         if (noti == NULL || text_input_max_length == NULL)
1513                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1514
1515         *text_input_max_length = noti->text_input_max_length;
1516
1517         return NOTIFICATION_ERROR_NONE;
1518 }
1519
1520 EXPORT_API int notification_post_with_event_cb_for_uid(notification_h noti, event_handler_cb cb,
1521                                                         void *userdata, uid_t uid)
1522 {
1523         int ret;
1524         int priv_id;
1525         notification_event_cb_info_s *info = NULL;
1526         GList *find_list;
1527
1528         if (noti == NULL || cb == NULL)
1529                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1530
1531         if (noti->type <= NOTIFICATION_TYPE_NONE || noti->type >= NOTIFICATION_TYPE_MAX)
1532                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1533
1534         noti->insert_time = time(NULL);
1535         noti->event_flag = true;
1536         noti->uid = uid;
1537
1538         ret = notification_ipc_request_insert(noti, &priv_id);
1539         if (ret != NOTIFICATION_ERROR_NONE)
1540                 return ret;
1541
1542         noti->priv_id = priv_id;
1543
1544         __noti_event_cb_list = g_list_first(__noti_event_cb_list);
1545         find_list = g_list_find_custom(__noti_event_cb_list, GUINT_TO_POINTER(priv_id),
1546                                        (GCompareFunc)__priv_id_compare);
1547
1548         if (find_list) {
1549                 info = g_list_nth_data(find_list, 0);
1550                 info->cb = cb;
1551                 info->userdata = userdata;
1552         } else {
1553                 info = (notification_event_cb_info_s *)malloc(sizeof(notification_cb_info_s));
1554                 if (info == NULL) {
1555                         NOTIFICATION_ERR("malloc failed");
1556                         return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1557                 }
1558                 info->priv_id = priv_id;
1559                 info->cb = cb;
1560                 info->userdata = userdata;
1561                 __noti_event_cb_list = g_list_append(__noti_event_cb_list, info);
1562         }
1563
1564         return ret;
1565 }
1566
1567 EXPORT_API int notification_post_with_event_cb(notification_h noti, event_handler_cb cb, void *userdata)
1568 {
1569         return notification_post_with_event_cb_for_uid(noti, cb, userdata, getuid());
1570 }
1571
1572 EXPORT_API int notification_send_event(notification_h noti, int event_type)
1573 {
1574         int ret;
1575         bool event_flag;
1576
1577         if (noti == NULL)
1578                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1579
1580         if (!((event_type >= NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1
1581              && event_type < NOTIFICATION_EVENT_TYPE_MAX)
1582              || (event_type >= NOTIFICATION_EVENT_TYPE_HIDDEN_BY_USER
1583              && event_type <= NOTIFICATION_EVENT_TYPE_HIDDEN_BY_TIMEOUT)))
1584                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1585
1586         ret = notification_get_event_flag(noti, &event_flag);
1587         if (ret != NOTIFICATION_ERROR_NONE || event_flag == false)
1588                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1589
1590         ret = notification_ipc_send_event(noti, event_type);
1591
1592         return ret;
1593 }
1594
1595 EXPORT_API int notification_get_event_flag(notification_h noti, bool *flag)
1596 {
1597         if (noti == NULL || flag == NULL)
1598                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1599
1600         *flag = noti->event_flag;
1601
1602         return NOTIFICATION_ERROR_NONE;
1603 }