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