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