Modify notification register changed callback
[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
47 typedef enum __notification_cb_type {
48         NOTIFICATION_CB_NORMAL = 1,
49         NOTIFICATION_CB_DETAILED,
50 } _notification_cb_type_e;
51
52 struct _notification_cb_info {
53         _notification_cb_type_e cb_type;
54         void (*changed_cb) (void *data, notification_type_e type);
55         void (*detailed_changed_cb) (void *data, notification_type_e type, notification_op *op_list, int num_op);
56         void *data;
57 };
58
59 static GHashTable *_noti_cb_hash = NULL;
60
61 static void __free_changed_cb_info(gpointer data)
62 {
63         notification_cb_info_s *noti_cb_info = (notification_cb_info_s *)data;
64         if (noti_cb_info)
65                 free(noti_cb_info);
66 }
67
68 static void __free_changed_cb_hash(gpointer data)
69 {
70         GList *changed_cb_list = (GList *)data;
71         if (changed_cb_list)
72                 g_list_free_full(changed_cb_list, __free_changed_cb_info);
73 }
74
75 void notification_call_changed_cb_for_uid(notification_op *op_list, int op_num, uid_t uid)
76 {
77         notification_type_e type = 0;
78         GList *noti_cb_list = NULL;
79         notification_cb_info_s *noti_cb_info = NULL;
80
81         if (_noti_cb_hash == NULL)
82                 return;
83
84         noti_cb_list = (GList *)g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
85
86         if (noti_cb_list == NULL)
87                 return;
88
89         if (op_list == NULL) {
90                 NOTIFICATION_ERR("invalid data");
91                 return;
92         }
93
94         noti_cb_list = g_list_first(noti_cb_list);
95         notification_get_type(op_list->noti, &type);
96
97         for (; noti_cb_list != NULL; noti_cb_list = noti_cb_list->next) {
98                 noti_cb_info = noti_cb_list->data;
99
100                 if (noti_cb_info->cb_type == NOTIFICATION_CB_NORMAL && noti_cb_info->changed_cb) {
101                         noti_cb_info->changed_cb(noti_cb_info->data, type);
102                 }
103                 if (noti_cb_info->cb_type == NOTIFICATION_CB_DETAILED && noti_cb_info->detailed_changed_cb) {
104                         noti_cb_info->detailed_changed_cb(noti_cb_info->data,
105                                         type, op_list, op_num);
106                 }
107         }
108 }
109
110 EXPORT_API int notification_add_deferred_task(
111                 void (*deferred_task_cb)(void *data), void *user_data)
112 {
113         if (deferred_task_cb == NULL)
114                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
115
116         return notification_ipc_add_deffered_task(deferred_task_cb, user_data);
117 }
118
119 EXPORT_API int notification_del_deferred_task(
120                 void (*deferred_task_cb)(void *data))
121 {
122         if (deferred_task_cb == NULL)
123                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
124
125         return notification_ipc_del_deffered_task(deferred_task_cb);
126 }
127
128 EXPORT_API int notification_resister_changed_cb_for_uid(
129                 void (*changed_cb)(void *data, notification_type_e type),
130                 void *user_data, uid_t uid)
131 {
132         GList *noti_cb_list = NULL;
133         notification_cb_info_s *noti_cb_info_new = NULL;
134
135         if (changed_cb == NULL)
136                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
137
138         if (notification_ipc_monitor_init(uid) != NOTIFICATION_ERROR_NONE)
139                 return NOTIFICATION_ERROR_IO_ERROR;
140
141         if (_noti_cb_hash == NULL)
142                 _noti_cb_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, __free_changed_cb_hash);
143
144         noti_cb_info_new = (notification_cb_info_s *)malloc(sizeof(notification_cb_info_s));
145         if (noti_cb_info_new == NULL) {
146                 NOTIFICATION_ERR("malloc failed");
147                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
148         }
149
150         noti_cb_info_new->cb_type = NOTIFICATION_CB_NORMAL;
151         noti_cb_info_new->changed_cb = changed_cb;
152         noti_cb_info_new->detailed_changed_cb = NULL;
153         noti_cb_info_new->data = user_data;
154
155         noti_cb_list = g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
156
157         if (noti_cb_list == NULL) {
158                 noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
159                 g_hash_table_insert(_noti_cb_hash, GUINT_TO_POINTER(uid), noti_cb_list);
160         } else {
161                 noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
162         }
163
164         return NOTIFICATION_ERROR_NONE;
165 }
166
167 EXPORT_API int notification_resister_changed_cb(
168                 void (*changed_cb)(void *data, notification_type_e type),
169                 void *user_data)
170 {
171         return notification_resister_changed_cb_for_uid(changed_cb, user_data, getuid());
172 }
173
174 EXPORT_API int notification_unresister_changed_cb_for_uid(
175                 void (*changed_cb)(void *data, notification_type_e type), uid_t uid)
176 {
177         notification_cb_info_s *noti_cb_info = NULL;
178         GList *noti_cb_list = NULL;
179
180         if (changed_cb == NULL)
181                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
182
183         if (_noti_cb_hash == NULL)
184                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
185
186         noti_cb_list = (GList *)g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
187
188         if (noti_cb_list == NULL)
189                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
190
191         noti_cb_list = g_list_first(noti_cb_list);
192
193         for (; noti_cb_list != NULL; noti_cb_list = noti_cb_list->next) {
194                 noti_cb_info = noti_cb_list->data;
195                 if (noti_cb_info->detailed_changed_cb == changed_cb) {
196                         noti_cb_list = g_list_remove(g_list_first(noti_cb_list), noti_cb_info);
197
198                         if (noti_cb_list == NULL)
199                                 g_hash_table_steal(_noti_cb_hash, GUINT_TO_POINTER(uid));
200
201                         if (g_hash_table_size(_noti_cb_hash) == 0)
202                                 notification_ipc_monitor_fini();
203
204                         return NOTIFICATION_ERROR_NONE;
205                 }
206         }
207
208         return NOTIFICATION_ERROR_INVALID_PARAMETER;
209 }
210
211 EXPORT_API int notification_unresister_changed_cb(
212                 void (*changed_cb)(void *data, notification_type_e type))
213 {
214         return notification_unresister_changed_cb_for_uid(changed_cb, getuid());
215 }
216
217 EXPORT_API int notification_update_progress(notification_h noti,
218                 int priv_id,
219                 double progress)
220 {
221         char *caller_pkgname = NULL;
222         int input_priv_id = 0;
223         int ret = 0;
224         double input_progress = 0.0;
225
226         if (priv_id <= NOTIFICATION_PRIV_ID_NONE) {
227                 if (noti == NULL)
228                         return NOTIFICATION_ERROR_INVALID_PARAMETER;
229                 else
230                         input_priv_id = noti->priv_id;
231
232         } else {
233                 input_priv_id = priv_id;
234         }
235
236         if (noti == NULL)
237                 caller_pkgname = notification_get_pkgname_by_pid();
238         else
239                 caller_pkgname = strdup(noti->caller_pkgname);
240
241         if (progress < 0.0)
242                 input_progress = 0.0;
243         else if (progress > 1.0)
244                 input_progress = 1.0;
245         else
246                 input_progress = progress;
247
248         ret = notification_ongoing_update_progress(caller_pkgname, input_priv_id,
249                         input_progress);
250
251         if (caller_pkgname)
252                 free(caller_pkgname);
253
254         return ret;
255 }
256
257 EXPORT_API int notification_update_size(notification_h noti,
258                 int priv_id,
259                 double size)
260 {
261         char *caller_pkgname = NULL;
262         int input_priv_id = 0;
263         int ret = 0;
264         double input_size = 0.0;
265
266         if (priv_id <= NOTIFICATION_PRIV_ID_NONE) {
267                 if (noti == NULL)
268                         return NOTIFICATION_ERROR_INVALID_PARAMETER;
269                 else
270                         input_priv_id = noti->priv_id;
271         } else {
272                 input_priv_id = priv_id;
273         }
274
275         if (noti == NULL)
276                 caller_pkgname = notification_get_pkgname_by_pid();
277         else
278                 caller_pkgname = strdup(noti->caller_pkgname);
279
280         if (size < 0.0)
281                 input_size = 0.0;
282         else
283                 input_size = size;
284
285         ret = notification_ongoing_update_size(caller_pkgname, input_priv_id,
286                         input_size);
287
288         if (caller_pkgname)
289                 free(caller_pkgname);
290
291         return ret;
292 }
293
294 EXPORT_API int notification_update_content(notification_h noti,
295                 int priv_id,
296                 const char *content)
297 {
298         char *caller_pkgname = NULL;
299         int input_priv_id = 0;
300         int ret = 0;
301
302         if (priv_id <= NOTIFICATION_PRIV_ID_NONE) {
303                 if (noti == NULL)
304                         return NOTIFICATION_ERROR_INVALID_PARAMETER;
305                 else
306                         input_priv_id = noti->priv_id;
307
308         } else {
309                 input_priv_id = priv_id;
310         }
311
312         if (noti == NULL)
313                 caller_pkgname = notification_get_pkgname_by_pid();
314         else
315                 caller_pkgname = strdup(noti->caller_pkgname);
316
317         ret = notification_ongoing_update_content(caller_pkgname, input_priv_id,
318                         content);
319
320         if (caller_pkgname)
321                 free(caller_pkgname);
322
323         return ret;
324 }
325
326 /* notification_set_icon will be removed */
327 /* LCOV_EXCL_START */
328 EXPORT_API int notification_set_icon(notification_h noti,
329                 const char *icon_path)
330 {
331         int ret_err = NOTIFICATION_ERROR_NONE;
332
333         ret_err =
334                 notification_set_image(noti, NOTIFICATION_IMAGE_TYPE_ICON,
335                                 icon_path);
336
337         return ret_err;
338 }
339 /* LCOV_EXCL_STOP */
340
341 /* notification_get_icon will be removed */
342 /* LCOV_EXCL_START */
343 EXPORT_API int notification_get_icon(notification_h noti,
344                 char **icon_path)
345 {
346         int ret_err = NOTIFICATION_ERROR_NONE;
347         char *ret_image_path = NULL;
348
349         ret_err =
350                 notification_get_image(noti, NOTIFICATION_IMAGE_TYPE_ICON,
351                                 &ret_image_path);
352
353         if (ret_err == NOTIFICATION_ERROR_NONE && icon_path != NULL)
354                 *icon_path = ret_image_path;
355
356         return ret_err;
357 }
358 /* LCOV_EXCL_STOP */
359
360 EXPORT_API int notification_translate_localized_text(notification_h noti)
361 {
362         int noti_err = NOTIFICATION_ERROR_NONE;
363         char *ret_text = NULL;
364         char buf_key[32];
365         char *bundle_val = NULL;
366         char *new_text;
367         bundle *b;
368         notification_text_type_e type = NOTIFICATION_TEXT_TYPE_TITLE;
369
370         for (; type < NOTIFICATION_TEXT_TYPE_MAX; type++) {
371                 noti_err = notification_get_text(noti, type, &ret_text);
372                 if (noti_err == NOTIFICATION_ERROR_NONE && ret_text) {
373                         if (noti->b_text == NULL) {
374                                 noti->b_text = bundle_create();
375                                 if (noti->b_text == NULL)
376                                         return NOTIFICATION_ERROR_OUT_OF_MEMORY;
377                         }
378
379                         b = noti->b_text;
380
381                         new_text = strdup(ret_text);
382
383                         snprintf(buf_key, sizeof(buf_key), "%d", type);
384                         bundle_get_str(b, buf_key, &bundle_val);
385                         if (bundle_val != NULL)
386                                 bundle_del(b, buf_key);
387
388                         bundle_add_str(b, buf_key, new_text);
389                         free(new_text);
390                         new_text = NULL;
391
392                         noti->num_format_args = 0;
393                         bundle_val = NULL;
394                 }
395         }
396
397         if (noti->b_key) {
398                 bundle_free(noti->b_key);
399                 noti->b_key = NULL;
400         }
401
402         return noti_err;
403 }
404
405 /* LCOV_EXCL_START */
406 EXPORT_API int notification_set_title(notification_h noti,
407                 const char *title,
408                 const char *loc_title)
409 {
410         int noti_err = NOTIFICATION_ERROR_NONE;
411
412         noti_err = notification_set_text(noti, NOTIFICATION_TEXT_TYPE_TITLE,
413                         title, loc_title,
414                         NOTIFICATION_VARIABLE_TYPE_NONE);
415
416         return noti_err;
417 }
418 /* LCOV_EXCL_STOP */
419
420 /* LCOV_EXCL_START */
421 EXPORT_API int notification_get_title(notification_h noti,
422                 char **title,
423                 char **loc_title)
424 {
425         int noti_err = NOTIFICATION_ERROR_NONE;
426         char *ret_text = NULL;
427
428         noti_err =
429                 notification_get_text(noti, NOTIFICATION_TEXT_TYPE_TITLE,
430                                 &ret_text);
431
432         if (title != NULL)
433                 *title = ret_text;
434
435         if (loc_title != NULL)
436                 *loc_title = NULL;
437
438         return noti_err;
439 }
440 /* LCOV_EXCL_STOP */
441
442 /* LCOV_EXCL_START */
443 EXPORT_API int notification_set_content(notification_h noti,
444                 const char *content,
445                 const char *loc_content)
446 {
447         int noti_err = NOTIFICATION_ERROR_NONE;
448
449         noti_err = notification_set_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT,
450                         content, loc_content,
451                         NOTIFICATION_VARIABLE_TYPE_NONE);
452
453         return noti_err;
454 }
455 /* LCOV_EXCL_STOP */
456
457 /* LCOV_EXCL_START */
458 EXPORT_API int notification_get_content(notification_h noti,
459                 char **content,
460                 char **loc_content)
461 {
462         int noti_err = NOTIFICATION_ERROR_NONE;
463         char *ret_text = NULL;
464
465         noti_err =
466                 notification_get_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT,
467                                 &ret_text);
468
469         if (content != NULL)
470                 *content = ret_text;
471
472         if (loc_content != NULL)
473                 *loc_content = NULL;
474
475         return noti_err;
476
477 #if 0
478         ret =
479                 vconf_get_bool
480                 (VCONFKEY_SETAPPL_STATE_TICKER_NOTI_DISPLAY_CONTENT_BOOL, &boolval);
481
482         if (ret == -1 || boolval == 0) {
483                 if (content != NULL && noti->default_content != NULL)
484                         *content = noti->default_content;
485
486                 if (loc_content != NULL && noti->loc_default_content != NULL)
487                         *loc_content = noti->loc_default_content;
488         }
489 #endif
490 }
491 /* LCOV_EXCL_STOP */
492
493 /* LCOV_EXCL_START */
494 EXPORT_API int notification_set_application(notification_h noti,
495                 const char *pkgname)
496 {
497         if (noti == NULL || pkgname == NULL)
498                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
499
500         if (noti->launch_pkgname)
501                 free(noti->launch_pkgname);
502
503         noti->launch_pkgname = strdup(pkgname);
504
505         return NOTIFICATION_ERROR_NONE;
506 }
507 /* LCOV_EXCL_STOP */
508
509 /* LCOV_EXCL_START */
510 EXPORT_API int notification_get_application(notification_h noti,
511                 char **pkgname)
512 {
513         if (noti == NULL || pkgname == NULL)
514                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
515
516         if (noti->launch_pkgname)
517                 *pkgname = noti->launch_pkgname;
518         else
519                 *pkgname = noti->caller_pkgname;
520
521         return NOTIFICATION_ERROR_NONE;
522 }
523 /* LCOV_EXCL_STOP */
524
525 /* LCOV_EXCL_START */
526 EXPORT_API int notification_set_args(notification_h noti, bundle *args,
527                 bundle *group_args)
528 {
529         if (noti == NULL || args == NULL)
530                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
531
532         if (noti->args)
533                 bundle_free(noti->args);
534
535         noti->args = bundle_dup(args);
536
537         if (noti->group_args) {
538                 bundle_free(noti->group_args);
539                 noti->group_args = NULL;
540         }
541
542         if (group_args != NULL)
543                 noti->group_args = bundle_dup(group_args);
544
545         return NOTIFICATION_ERROR_NONE;
546 }
547 /* LCOV_EXCL_STOP */
548
549 /* LCOV_EXCL_START */
550 EXPORT_API int notification_get_args(notification_h noti,
551                 bundle **args,
552                 bundle **group_args)
553 {
554         if (noti == NULL || args == NULL)
555                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
556
557         if (noti->args)
558                 *args = noti->args;
559         else
560                 *args = NULL;
561
562         if (group_args != NULL && noti->group_args)
563                 *group_args = noti->group_args;
564
565         return NOTIFICATION_ERROR_NONE;
566 }
567 /* LCOV_EXCL_STOP */
568
569 /* LCOV_EXCL_START */
570 int notification_get_grouping_list_for_uid(notification_type_e type, int count,
571                 notification_list_h *list, uid_t uid)
572 {
573         notification_list_h get_list = NULL;
574         int ret = 0;
575
576         if (list == NULL)
577                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
578
579         ret = notification_noti_get_grouping_list(type, count, &get_list, uid);
580         if (ret != NOTIFICATION_ERROR_NONE)
581                 return ret;
582
583         *list = get_list;
584
585         return NOTIFICATION_ERROR_NONE;
586 }
587
588 EXPORT_API int notification_get_grouping_list(notification_type_e type, int count,
589                 notification_list_h *list)
590 {
591         return notification_get_grouping_list_for_uid(type, count, list, getuid());
592 }
593 /* LCOV_EXCL_STOP */
594
595 /* LCOV_EXCL_START */
596 EXPORT_API int notification_delete_group_by_group_id(const char *pkgname,
597                 notification_type_e type,
598                 int group_id)
599 {
600         int ret = 0;
601         char *caller_pkgname = NULL;
602
603         if (pkgname == NULL)
604                 caller_pkgname = notification_get_pkgname_by_pid();
605         else
606                 caller_pkgname = strdup(pkgname);
607
608         ret = notification_ipc_request_delete_multiple(type, caller_pkgname, getuid());
609
610         if (caller_pkgname)
611                 free(caller_pkgname);
612
613         return ret;
614 }
615 /* LCOV_EXCL_STOP */
616
617 /* LCOV_EXCL_START */
618 int notification_delete_group_by_priv_id_for_uid(const char *pkgname,
619                 notification_type_e type,
620                 int priv_id, uid_t uid)
621 {
622         int ret = 0;
623         char *caller_pkgname = NULL;
624
625         if (pkgname == NULL)
626                 caller_pkgname = notification_get_pkgname_by_pid();
627         else
628                 caller_pkgname = strdup(pkgname);
629
630         ret = notification_ipc_request_delete_single(type, caller_pkgname, priv_id, uid);
631
632         if (caller_pkgname)
633                 free(caller_pkgname);
634
635         return ret;
636 }
637 /* LCOV_EXCL_STOP */
638
639 /* LCOV_EXCL_START */
640 EXPORT_API int notification_delete_group_by_priv_id(const char *pkgname,
641                 notification_type_e type,
642                 int priv_id)
643 {
644         return notification_delete_group_by_priv_id_for_uid(pkgname, type, priv_id, getuid());
645 }
646
647 int notification_get_count_for_uid(notification_type_e type,
648                 const char *pkgname,
649                 int group_id,
650                 int priv_id, int *count,
651                 uid_t uid)
652 {
653         int ret = 0;
654         char *caller_pkgname = NULL;
655
656         if (count == NULL)
657                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
658
659         if (pkgname == NULL)
660                 caller_pkgname = notification_get_pkgname_by_pid();
661         else
662                 caller_pkgname = strdup(pkgname);
663
664         ret = notification_ipc_request_get_count(
665                         type,
666                         caller_pkgname,
667                         group_id,
668                         priv_id,
669                         count,
670                         uid);
671
672         if (caller_pkgname)
673                 free(caller_pkgname);
674
675         return ret;
676 }
677 /* LCOV_EXCL_STOP */
678
679 /* LCOV_EXCL_START */
680 EXPORT_API int notification_get_count(notification_type_e type,
681                 const char *pkgname,
682                 int group_id,
683                 int priv_id, int *count)
684 {
685         return notification_get_count_for_uid(type, pkgname, group_id, priv_id, count, getuid());
686 }
687
688 int notification_clear_for_uid(notification_type_e type, uid_t uid)
689 {
690         int ret = 0;
691
692         if (type <= NOTIFICATION_TYPE_NONE || type >= NOTIFICATION_TYPE_MAX)
693                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
694
695         ret = notification_ipc_request_delete_multiple(type, NULL, uid);
696
697         return ret;
698 }
699 /* LCOV_EXCL_STOP */
700
701 /* LCOV_EXCL_START */
702 EXPORT_API int notification_clear(notification_type_e type)
703 {
704         return notification_clear_for_uid(type, getuid());
705 }
706
707 EXPORT_API int notification_op_get_data(notification_op *noti_op, notification_op_data_type_e type,
708                 void *data)
709 {
710         if (noti_op == NULL || data == NULL)
711                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
712
713         switch (type) {
714         case NOTIFICATION_OP_DATA_TYPE:
715                 *((int *)data) = noti_op->type;
716                 break;
717         case NOTIFICATION_OP_DATA_PRIV_ID:
718                 *((int *)data) = noti_op->priv_id;
719                 break;
720         case NOTIFICATION_OP_DATA_NOTI:
721                 *((notification_h *)data) = noti_op->noti;
722                 break;
723         case NOTIFICATION_OP_DATA_EXTRA_INFO_1:
724                 *((int *)data) = noti_op->extra_info_1;
725                 break;
726         case NOTIFICATION_OP_DATA_EXTRA_INFO_2:
727                 *((int *)data) = noti_op->extra_info_2;
728                 break;
729         default:
730                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
731                 break;
732         }
733
734         return NOTIFICATION_ERROR_NONE;
735 }
736 /* LCOV_EXCL_STOP */
737
738 /* LCOV_EXCL_START */
739 EXPORT_API int notification_set_pkgname(notification_h noti,
740                 const char *pkgname)
741 {
742         /* check noti and pkgname are valid data */
743         if (noti == NULL || pkgname == NULL)
744                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
745
746         /* Remove previous caller pkgname */
747         if (noti->caller_pkgname) {
748                 free(noti->caller_pkgname);
749                 noti->caller_pkgname = NULL;
750         }
751
752         noti->caller_pkgname = strdup(pkgname);
753
754         return NOTIFICATION_ERROR_NONE;
755 }
756 /* LCOV_EXCL_STOP */
757
758 /* LCOV_EXCL_START */
759 int notification_delete_all_by_type_for_uid(const char *pkgname,
760                 notification_type_e type, uid_t uid)
761 {
762         int ret = 0;
763         char *caller_pkgname = NULL;
764
765         if (type <= NOTIFICATION_TYPE_NONE || type >= NOTIFICATION_TYPE_MAX)
766                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
767
768         if (pkgname == NULL)
769                 caller_pkgname = notification_get_pkgname_by_pid();
770         else
771                 caller_pkgname = strdup(pkgname);
772
773         ret = notification_ipc_request_delete_multiple(type, caller_pkgname, uid);
774
775         if (caller_pkgname)
776                 free(caller_pkgname);
777
778         return ret;
779 }
780 /* LCOV_EXCL_STOP */
781
782 /* LCOV_EXCL_START */
783 EXPORT_API int notification_delete_all_by_type(const char *pkgname,
784                 notification_type_e type)
785 {
786         return notification_delete_all_by_type_for_uid(pkgname, type, getuid());
787 }
788
789 int notification_delete_by_priv_id_for_uid(const char *pkgname,
790                 notification_type_e type,
791                 int priv_id,
792                 uid_t uid)
793 {
794         int ret = 0;
795         char *caller_pkgname = NULL;
796
797         if (priv_id <= NOTIFICATION_PRIV_ID_NONE)
798                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
799
800         if (pkgname == NULL)
801                 caller_pkgname = notification_get_pkgname_by_pid();
802         else
803                 caller_pkgname = strdup(pkgname);
804
805         ret = notification_ipc_request_delete_single(type, caller_pkgname, priv_id, uid);
806
807         if (caller_pkgname)
808                 free(caller_pkgname);
809
810         return ret;
811 }
812 /* LCOV_EXCL_STOP */
813
814 /* LCOV_EXCL_START */
815 EXPORT_API int notification_delete_by_priv_id(const char *pkgname,
816                 notification_type_e type,
817                 int priv_id)
818 {
819         return notification_delete_by_priv_id_for_uid(pkgname, type, priv_id, getuid());
820 }
821
822 EXPORT_API int notification_set_execute_option(notification_h noti,
823                 notification_execute_type_e type,
824                 const char *text,
825                 const char *key,
826                 bundle *service_handle)
827 {
828         char buf_key[32] = { 0, };
829         char *ret_val = NULL;
830         bundle *b = NULL;
831
832         if (noti == NULL)
833                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
834
835         if (type <= NOTIFICATION_EXECUTE_TYPE_NONE
836                         || type >= NOTIFICATION_EXECUTE_TYPE_MAX)
837                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
838
839         /* Create execute option bundle if does not exist */
840         if (noti->b_execute_option == NULL)
841                 noti->b_execute_option = bundle_create();
842
843         b = noti->b_execute_option;
844
845         /* Save text */
846         if (text != NULL) {
847                 /* Make text key */
848                 snprintf(buf_key, sizeof(buf_key), "text%d", type);
849
850                 /* Check text key exist */
851                 bundle_get_str(b, buf_key, &ret_val);
852                 if (ret_val != NULL)
853                         /* Remove previous data */
854                         bundle_del(b, buf_key);
855
856                 /* Add text data */
857                 bundle_add_str(b, buf_key, text);
858         }
859
860         /* Save key */
861         if (key != NULL) {
862                 /* Make key key */
863                 snprintf(buf_key, sizeof(buf_key), "key%d", type);
864
865                 /* Check key key exist */
866                 bundle_get_str(b, buf_key, &ret_val);
867                 if (ret_val != NULL)
868                         /* Remove previous data */
869                         bundle_del(b, buf_key);
870
871                 /* Add text data */
872                 bundle_add_str(b, buf_key, key);
873         }
874
875         switch ((int)type) {
876         case NOTIFICATION_EXECUTE_TYPE_RESPONDING:
877                 /* Remove previous data if exist */
878                 if (noti->b_service_responding != NULL) {
879                         bundle_free(noti->b_service_responding);
880                         noti->b_service_responding = NULL;
881                 }
882
883                 /* Save service handle */
884                 if (service_handle != NULL)
885                         noti->b_service_responding = bundle_dup(service_handle);
886
887                 break;
888         case NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH:
889                 /* Remove previous data if exist */
890                 if (noti->b_service_single_launch != NULL) {
891                         bundle_free(noti->b_service_single_launch);
892                         noti->b_service_single_launch = NULL;
893                 }
894
895                 /* Save service handle */
896                 if (service_handle != NULL)
897                         noti->b_service_single_launch =
898                                 bundle_dup(service_handle);
899
900                 break;
901         case NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH:
902                 /* Remove previous data if exist */
903                 if (noti->b_service_multi_launch != NULL) {
904                         bundle_free(noti->b_service_multi_launch);
905                         noti->b_service_multi_launch = NULL;
906                 }
907
908                 /* Save service handle */
909                 if (service_handle != NULL)
910                         noti->b_service_multi_launch =
911                                 bundle_dup(service_handle);
912
913                 break;
914         }
915
916         return NOTIFICATION_ERROR_NONE;
917 }
918 /* LCOV_EXCL_STOP */
919
920 /* LCOV_EXCL_START */
921 EXPORT_API int notification_get_id(notification_h noti,
922                 int *group_id, int *priv_id)
923 {
924         /* check noti is valid data */
925         if (noti == NULL)
926                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
927
928         /* Check group_id is valid data */
929         if (group_id) {
930                 /* Set group id */
931                 if (noti->group_id < NOTIFICATION_GROUP_ID_NONE)
932                         *group_id = NOTIFICATION_GROUP_ID_NONE;
933                 else
934                         *group_id = noti->group_id;
935         }
936
937         /* Check priv_id is valid data */
938         if (priv_id)
939                 /* Set priv_id */
940                 *priv_id = noti->priv_id;
941
942         return NOTIFICATION_ERROR_NONE;
943 }
944 /* LCOV_EXCL_STOP */
945
946 /* LCOV_EXCL_START */
947 notification_h notification_load_for_uid(char *pkgname,
948                 int priv_id, uid_t uid)
949 {
950         int ret = 0;
951         notification_h noti = NULL;
952
953         noti = (notification_h)calloc(1, sizeof(struct _notification));
954         if (noti == NULL) {
955                 NOTIFICATION_ERR("NO MEMORY : noti == NULL");
956                 return NULL;
957         }
958
959         ret = notification_ipc_request_load_noti_by_priv_id(noti, pkgname, priv_id, uid);
960         if (ret != NOTIFICATION_ERROR_NONE) {
961                 notification_free(noti);
962                 return NULL;
963         }
964
965         return noti;
966 }
967 /* LCOV_EXCL_STOP */
968
969 /* LCOV_EXCL_START */
970 EXPORT_API notification_h notification_load(char *pkgname,
971                 int priv_id)
972 {
973         return notification_load_for_uid(pkgname, priv_id, getuid());
974 }
975 /* LCOV_EXCL_STOP */
976
977 /* LCOV_EXCL_START */
978 EXPORT_API notification_h notification_new(notification_type_e type,
979                 int group_id, int priv_id)
980 {
981         return notification_create(type);
982 }
983
984 static void _notification_get_text_domain(notification_h noti)
985 {
986 }
987 /* LCOV_EXCL_STOP */
988
989 /* LCOV_EXCL_START */
990 EXPORT_API int notification_get_execute_option(notification_h noti,
991                 notification_execute_type_e type,
992                 const char **text,
993                 bundle **service_handle)
994 {
995         char buf_key[32] = { 0, };
996         char *ret_val = NULL;
997         char *get_str = NULL;
998         bundle *b = NULL;
999
1000         if (noti == NULL)
1001                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1002
1003         if (type <= NOTIFICATION_EXECUTE_TYPE_NONE
1004                         || type >= NOTIFICATION_EXECUTE_TYPE_MAX)
1005                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1006
1007
1008         switch (type) {
1009         case NOTIFICATION_EXECUTE_TYPE_RESPONDING:
1010                 b = noti->b_service_responding;
1011                 break;
1012         case NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH:
1013                 b = noti->b_service_single_launch;
1014                 break;
1015         case NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH:
1016                 b = noti->b_service_multi_launch;
1017                 break;
1018         default:
1019                 break;
1020         }
1021
1022         if (b != NULL) {
1023                 /* Return text */
1024                 if (text != NULL) {
1025                         /*  Get text domain and dir */
1026                         if (noti->domain == NULL || noti->dir == NULL)
1027                                 _notification_get_text_domain(noti);
1028
1029                         /* Make key */
1030                         snprintf(buf_key, sizeof(buf_key), "key%d", type);
1031
1032                         /* Check key key exist */
1033                         bundle_get_str(b, buf_key, &ret_val);
1034                         if (ret_val != NULL && noti->domain != NULL
1035                                         && noti->dir != NULL) {
1036                                 /* Get application string */
1037                                 bindtextdomain(noti->domain, noti->dir);
1038
1039                                 get_str = dgettext(noti->domain, ret_val);
1040
1041                                 *text = get_str;
1042                         } else if (ret_val != NULL) {
1043                                 /* Get system string */
1044                                 get_str = dgettext("sys_string", ret_val);
1045
1046                                 *text = get_str;
1047                         } else {
1048                                 /* Get basic text */
1049                                 snprintf(buf_key, sizeof(buf_key), "text%d",
1050                                                 type);
1051
1052                                 bundle_get_str(b, buf_key, &ret_val);
1053
1054                                 *text = ret_val;
1055                         }
1056                 }
1057         }
1058
1059         if (service_handle != NULL)
1060                 *service_handle = b;
1061
1062         return NOTIFICATION_ERROR_NONE;
1063 }
1064 /* LCOV_EXCL_STOP */
1065
1066 EXPORT_API int notification_insert_for_uid(notification_h noti,
1067                 int *priv_id, uid_t uid)
1068 {
1069         int ret = 0;
1070         int id = 0;
1071
1072         /* Check noti is vaild data */
1073         if (noti == NULL)
1074                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1075
1076         /* Check noti type is valid type */
1077         if (noti->type <= NOTIFICATION_TYPE_NONE
1078                         || noti->type >= NOTIFICATION_TYPE_MAX)
1079                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1080
1081         noti->uid = uid;
1082         /* Save insert time */
1083         noti->insert_time = time(NULL);
1084         ret = notification_ipc_request_insert(noti, &id);
1085         if (ret != NOTIFICATION_ERROR_NONE)
1086                 return ret;
1087
1088         noti->priv_id = id;
1089         NOTIFICATION_DBG("from master:%d", id);
1090
1091         /* If priv_id is valid data, set priv_id */
1092         if (priv_id != NULL)
1093                 *priv_id = noti->priv_id;
1094
1095         return NOTIFICATION_ERROR_NONE;
1096 }
1097
1098 EXPORT_API int notification_insert(notification_h noti,
1099                 int *priv_id)
1100 {
1101         return notification_insert_for_uid(noti, priv_id, getuid());
1102 }
1103
1104 EXPORT_API int notification_update_async_for_uid(notification_h noti,
1105                 void (*result_cb)(int priv_id, int result, void *data), void *user_data, uid_t uid)
1106 {
1107         int ret = 0;
1108         if (noti == NULL)
1109                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1110
1111         noti->uid = uid;
1112         /* Update insert time ? */
1113         noti->insert_time = time(NULL);
1114         ret = notification_ipc_request_update_async(noti, result_cb, user_data);
1115
1116         return ret;
1117 }
1118
1119 EXPORT_API int notification_update_async(notification_h noti,
1120                 void (*result_cb)(int priv_id, int result, void *data), void *user_data)
1121 {
1122         return notification_update_async_for_uid(noti, result_cb, user_data, getuid());
1123 }
1124
1125 EXPORT_API int notification_register_detailed_changed_cb_for_uid(
1126                 void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
1127                 void *user_data, uid_t uid)
1128 {
1129         GList *noti_cb_list = NULL;
1130         notification_cb_info_s *noti_cb_info_new = NULL;
1131
1132         if (detailed_changed_cb == NULL)
1133                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1134
1135         if (notification_ipc_monitor_init(uid) != NOTIFICATION_ERROR_NONE)
1136                 return NOTIFICATION_ERROR_IO_ERROR;
1137
1138         if (_noti_cb_hash == NULL)
1139                 _noti_cb_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, __free_changed_cb_hash);
1140
1141         noti_cb_info_new = (notification_cb_info_s *)malloc(sizeof(notification_cb_info_s));
1142         if (noti_cb_info_new == NULL) {
1143                 NOTIFICATION_ERR("malloc failed");
1144                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1145         }
1146
1147         noti_cb_info_new->cb_type = NOTIFICATION_CB_DETAILED;
1148         noti_cb_info_new->changed_cb = NULL;
1149         noti_cb_info_new->detailed_changed_cb = detailed_changed_cb;
1150         noti_cb_info_new->data = user_data;
1151
1152         noti_cb_list = g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
1153
1154         if (noti_cb_list == NULL) {
1155                 noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
1156                 g_hash_table_insert(_noti_cb_hash, GUINT_TO_POINTER(uid), noti_cb_list);
1157         } else {
1158                 noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
1159         }
1160
1161         return NOTIFICATION_ERROR_NONE;
1162 }
1163
1164 EXPORT_API int notification_register_detailed_changed_cb(
1165                 void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
1166                 void *user_data)
1167 {
1168         return notification_register_detailed_changed_cb_for_uid(detailed_changed_cb, user_data, getuid());
1169 }
1170
1171 EXPORT_API int notification_unregister_detailed_changed_cb_for_uid(
1172                 void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
1173                 void *user_data, uid_t uid)
1174 {
1175         notification_cb_info_s *noti_cb_info = NULL;
1176         GList *noti_cb_list = NULL;
1177
1178         if (detailed_changed_cb == NULL)
1179                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1180
1181         if (_noti_cb_hash == NULL)
1182                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1183
1184         noti_cb_list = (GList *)g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
1185
1186         if (noti_cb_list == NULL)
1187                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1188
1189         noti_cb_list = g_list_first(noti_cb_list);
1190
1191         for (; noti_cb_list != NULL; noti_cb_list = noti_cb_list->next) {
1192                 noti_cb_info = noti_cb_list->data;
1193                 if (noti_cb_info->detailed_changed_cb == detailed_changed_cb) {
1194                         noti_cb_list = g_list_remove(g_list_first(noti_cb_list), noti_cb_info);
1195
1196                         if (noti_cb_list == NULL)
1197                                 g_hash_table_steal(_noti_cb_hash, GUINT_TO_POINTER(uid));
1198
1199                         if (g_hash_table_size(_noti_cb_hash) == 0)
1200                                 notification_ipc_monitor_fini();
1201
1202                         return NOTIFICATION_ERROR_NONE;
1203                 }
1204         }
1205
1206         return NOTIFICATION_ERROR_INVALID_PARAMETER;
1207 }
1208
1209 EXPORT_API int notification_unregister_detailed_changed_cb(
1210                 void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
1211                 void *user_data)
1212 {
1213         return notification_unregister_detailed_changed_cb_for_uid(detailed_changed_cb, user_data, getuid());
1214 }
1215
1216 /* LCOV_EXCL_START */
1217 EXPORT_API int notification_is_service_ready(void)
1218 {
1219         return notification_ipc_is_master_ready();
1220 }
1221 /* LCOV_EXCL_STOP */
1222
1223 EXPORT_API int notification_set_uid(notification_h noti,
1224                 uid_t uid)
1225 {
1226         if (noti == NULL)
1227                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1228
1229         noti->uid = uid;
1230         return NOTIFICATION_ERROR_NONE;
1231 }
1232
1233 EXPORT_API int notification_get_uid(notification_h noti,
1234                 uid_t *uid)
1235 {
1236         if (noti == NULL || uid == NULL)
1237                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1238
1239         *uid = noti->uid;
1240         return NOTIFICATION_ERROR_NONE;
1241 }
1242
1243 EXPORT_API int notification_post_for_uid(notification_h noti, uid_t uid)
1244 {
1245         int ret = 0;
1246         int id = 0;
1247
1248         /* Check noti is vaild data */
1249         if (noti == NULL)
1250                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1251
1252         /* Check noti type is valid type */
1253         if (noti->type <= NOTIFICATION_TYPE_NONE
1254                         || noti->type >= NOTIFICATION_TYPE_MAX)
1255                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1256
1257         /* Save insert time */
1258         noti->insert_time = time(NULL);
1259         noti->uid = uid;
1260
1261         ret = notification_ipc_request_insert(noti, &id);
1262         if (ret != NOTIFICATION_ERROR_NONE)
1263                 return ret;
1264
1265         noti->priv_id = id;
1266         NOTIFICATION_DBG("from master:%d", id);
1267
1268         return NOTIFICATION_ERROR_NONE;
1269 }
1270
1271 EXPORT_API int notification_update_for_uid(notification_h noti, uid_t uid)
1272 {
1273         int ret;
1274
1275         /* Check noti is valid data */
1276         if (noti != NULL) {
1277                 noti->uid = uid;
1278                 /* Update insert time ? */
1279                 noti->insert_time = time(NULL);
1280                 ret = notification_ipc_request_update(noti);
1281         } else {
1282                 notification_ipc_request_refresh(uid);
1283                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1284         }
1285
1286         return ret;
1287 }
1288
1289 EXPORT_API int notification_delete_for_uid(notification_h noti, uid_t uid)
1290 {
1291         int ret = 0;
1292
1293         if (noti == NULL)
1294                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1295
1296         ret = notification_ipc_request_delete_single(NOTIFICATION_TYPE_NONE, noti->caller_pkgname, noti->priv_id, uid);
1297
1298         return ret;
1299 }
1300
1301 EXPORT_API int notification_delete_all_for_uid(notification_type_e type, uid_t uid)
1302 {
1303         int ret = 0;
1304         char *caller_pkgname = NULL;
1305
1306         if (type <= NOTIFICATION_TYPE_NONE || type >= NOTIFICATION_TYPE_MAX)
1307                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1308
1309         caller_pkgname = notification_get_pkgname_by_pid();
1310
1311         ret = notification_ipc_request_delete_multiple(type, caller_pkgname, uid);
1312
1313         if (caller_pkgname)
1314                 free(caller_pkgname);
1315
1316         return ret;
1317 }
1318
1319 EXPORT_API notification_h notification_load_by_tag_for_uid(const char *tag, uid_t uid)
1320 {
1321         int ret = 0;
1322         notification_h noti = NULL;
1323         char *caller_pkgname = NULL;
1324
1325         if (tag == NULL) {
1326                 NOTIFICATION_ERR("Invalid parameter");
1327                 set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
1328                 return NULL;
1329         }
1330
1331         caller_pkgname = notification_get_pkgname_by_pid();
1332         if (!caller_pkgname) {
1333                 /* LCOV_EXCL_START */
1334                 NOTIFICATION_ERR("Failed to get a package name");
1335                 set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
1336                 return NULL;
1337                 /* LCOV_EXCL_STOP */
1338         }
1339
1340         noti = (notification_h)calloc(1, sizeof(struct _notification));
1341         if (noti == NULL) {
1342                 /* LCOV_EXCL_START */
1343                 NOTIFICATION_ERR("Failed to alloc a new notification");
1344                 set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
1345                 free(caller_pkgname);
1346
1347                 return NULL;
1348                 /* LCOV_EXCL_STOP */
1349         }
1350
1351         ret = notification_ipc_request_load_noti_by_tag(noti, caller_pkgname, (char *)tag, uid);
1352         free(caller_pkgname);
1353
1354         set_last_result(ret);
1355         if (ret != NOTIFICATION_ERROR_NONE) {
1356                 notification_free(noti);
1357                 return NULL;
1358         }
1359
1360         return noti;
1361 }