28d6fb8dc298631c784a4a7baaf9e5561cad34ab
[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         if (noti->b_key) {
402                 bundle_free(noti->b_key);
403                 noti->b_key = NULL;
404         }
405
406         return noti_err;
407 }
408
409 /* LCOV_EXCL_START */
410 EXPORT_API int notification_set_title(notification_h noti,
411                 const char *title,
412                 const char *loc_title)
413 {
414         int noti_err = NOTIFICATION_ERROR_NONE;
415
416         noti_err = notification_set_text(noti, NOTIFICATION_TEXT_TYPE_TITLE,
417                         title, loc_title,
418                         NOTIFICATION_VARIABLE_TYPE_NONE);
419
420         return noti_err;
421 }
422 /* LCOV_EXCL_STOP */
423
424 /* LCOV_EXCL_START */
425 EXPORT_API int notification_get_title(notification_h noti,
426                 char **title,
427                 char **loc_title)
428 {
429         int noti_err = NOTIFICATION_ERROR_NONE;
430         char *ret_text = NULL;
431
432         noti_err =
433                 notification_get_text(noti, NOTIFICATION_TEXT_TYPE_TITLE,
434                                 &ret_text);
435
436         if (title != NULL)
437                 *title = ret_text;
438
439         if (loc_title != NULL)
440                 *loc_title = NULL;
441
442         return noti_err;
443 }
444 /* LCOV_EXCL_STOP */
445
446 /* LCOV_EXCL_START */
447 EXPORT_API int notification_set_content(notification_h noti,
448                 const char *content,
449                 const char *loc_content)
450 {
451         int noti_err = NOTIFICATION_ERROR_NONE;
452
453         noti_err = notification_set_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT,
454                         content, loc_content,
455                         NOTIFICATION_VARIABLE_TYPE_NONE);
456
457         return noti_err;
458 }
459 /* LCOV_EXCL_STOP */
460
461 /* LCOV_EXCL_START */
462 EXPORT_API int notification_get_content(notification_h noti,
463                 char **content,
464                 char **loc_content)
465 {
466         int noti_err = NOTIFICATION_ERROR_NONE;
467         char *ret_text = NULL;
468
469         noti_err =
470                 notification_get_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT,
471                                 &ret_text);
472
473         if (content != NULL)
474                 *content = ret_text;
475
476         if (loc_content != NULL)
477                 *loc_content = NULL;
478
479         return noti_err;
480
481 #if 0
482         ret =
483                 vconf_get_bool
484                 (VCONFKEY_SETAPPL_STATE_TICKER_NOTI_DISPLAY_CONTENT_BOOL, &boolval);
485
486         if (ret == -1 || boolval == 0) {
487                 if (content != NULL && noti->default_content != NULL)
488                         *content = noti->default_content;
489
490                 if (loc_content != NULL && noti->loc_default_content != NULL)
491                         *loc_content = noti->loc_default_content;
492         }
493 #endif
494 }
495 /* LCOV_EXCL_STOP */
496
497 /* LCOV_EXCL_START */
498 EXPORT_API int notification_set_application(notification_h noti,
499                 const char *pkgname)
500 {
501         if (noti == NULL || pkgname == NULL)
502                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
503
504         if (noti->launch_pkgname)
505                 free(noti->launch_pkgname);
506
507         noti->launch_pkgname = strdup(pkgname);
508
509         return NOTIFICATION_ERROR_NONE;
510 }
511 /* LCOV_EXCL_STOP */
512
513 /* LCOV_EXCL_START */
514 EXPORT_API int notification_get_application(notification_h noti,
515                 char **pkgname)
516 {
517         if (noti == NULL || pkgname == NULL)
518                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
519
520         if (noti->launch_pkgname)
521                 *pkgname = noti->launch_pkgname;
522         else
523                 *pkgname = noti->caller_pkgname;
524
525         return NOTIFICATION_ERROR_NONE;
526 }
527 /* LCOV_EXCL_STOP */
528
529 /* LCOV_EXCL_START */
530 EXPORT_API int notification_set_args(notification_h noti, bundle *args,
531                 bundle *group_args)
532 {
533         if (noti == NULL || args == NULL)
534                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
535
536         if (noti->args)
537                 bundle_free(noti->args);
538
539         noti->args = bundle_dup(args);
540
541         if (noti->group_args) {
542                 bundle_free(noti->group_args);
543                 noti->group_args = NULL;
544         }
545
546         if (group_args != NULL)
547                 noti->group_args = bundle_dup(group_args);
548
549         return NOTIFICATION_ERROR_NONE;
550 }
551 /* LCOV_EXCL_STOP */
552
553 /* LCOV_EXCL_START */
554 EXPORT_API int notification_get_args(notification_h noti,
555                 bundle **args,
556                 bundle **group_args)
557 {
558         if (noti == NULL || args == NULL)
559                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
560
561         if (noti->args)
562                 *args = noti->args;
563         else
564                 *args = NULL;
565
566         if (group_args != NULL && noti->group_args)
567                 *group_args = noti->group_args;
568
569         return NOTIFICATION_ERROR_NONE;
570 }
571 /* LCOV_EXCL_STOP */
572
573 /* LCOV_EXCL_START */
574 int notification_get_grouping_list_for_uid(notification_type_e type, int count,
575                 notification_list_h *list, uid_t uid)
576 {
577         notification_list_h get_list = NULL;
578         int ret = 0;
579
580         if (list == NULL)
581                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
582
583         ret = notification_noti_get_grouping_list(type, count, &get_list, uid);
584         if (ret != NOTIFICATION_ERROR_NONE)
585                 return ret;
586
587         *list = get_list;
588
589         return NOTIFICATION_ERROR_NONE;
590 }
591
592 EXPORT_API int notification_get_grouping_list(notification_type_e type, int count,
593                 notification_list_h *list)
594 {
595         return notification_get_grouping_list_for_uid(type, count, list, getuid());
596 }
597 /* LCOV_EXCL_STOP */
598
599 /* LCOV_EXCL_START */
600 EXPORT_API int notification_delete_group_by_group_id(const char *pkgname,
601                 notification_type_e type,
602                 int group_id)
603 {
604         int ret = 0;
605         char *caller_pkgname = NULL;
606
607         if (pkgname == NULL)
608                 caller_pkgname = notification_get_pkgname_by_pid();
609         else
610                 caller_pkgname = strdup(pkgname);
611
612         ret = notification_ipc_request_delete_multiple(type, caller_pkgname, getuid());
613
614         if (caller_pkgname)
615                 free(caller_pkgname);
616
617         return ret;
618 }
619 /* LCOV_EXCL_STOP */
620
621 /* LCOV_EXCL_START */
622 int notification_delete_group_by_priv_id_for_uid(const char *pkgname,
623                 notification_type_e type,
624                 int priv_id, uid_t uid)
625 {
626         int ret = 0;
627         char *caller_pkgname = NULL;
628
629         if (pkgname == NULL)
630                 caller_pkgname = notification_get_pkgname_by_pid();
631         else
632                 caller_pkgname = strdup(pkgname);
633
634         ret = notification_ipc_request_delete_single(type, caller_pkgname, priv_id, uid);
635
636         if (caller_pkgname)
637                 free(caller_pkgname);
638
639         return ret;
640 }
641 /* LCOV_EXCL_STOP */
642
643 /* LCOV_EXCL_START */
644 EXPORT_API int notification_delete_group_by_priv_id(const char *pkgname,
645                 notification_type_e type,
646                 int priv_id)
647 {
648         return notification_delete_group_by_priv_id_for_uid(pkgname, type, priv_id, getuid());
649 }
650
651 int notification_get_count_for_uid(notification_type_e type,
652                 const char *pkgname,
653                 int group_id,
654                 int priv_id, int *count,
655                 uid_t uid)
656 {
657         int ret = 0;
658         char *caller_pkgname = NULL;
659
660         if (count == NULL)
661                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
662
663         if (pkgname == NULL)
664                 caller_pkgname = notification_get_pkgname_by_pid();
665         else
666                 caller_pkgname = strdup(pkgname);
667
668         ret = notification_ipc_request_get_count(
669                         type,
670                         caller_pkgname,
671                         group_id,
672                         priv_id,
673                         count,
674                         uid);
675
676         if (caller_pkgname)
677                 free(caller_pkgname);
678
679         return ret;
680 }
681 /* LCOV_EXCL_STOP */
682
683 /* LCOV_EXCL_START */
684 EXPORT_API int notification_get_count(notification_type_e type,
685                 const char *pkgname,
686                 int group_id,
687                 int priv_id, int *count)
688 {
689         return notification_get_count_for_uid(type, pkgname, group_id, priv_id, count, getuid());
690 }
691
692 int notification_clear_for_uid(notification_type_e type, uid_t uid)
693 {
694         int ret = 0;
695
696         if (type <= NOTIFICATION_TYPE_NONE || type >= NOTIFICATION_TYPE_MAX)
697                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
698
699         ret = notification_ipc_request_delete_multiple(type, NULL, uid);
700
701         return ret;
702 }
703 /* LCOV_EXCL_STOP */
704
705 /* LCOV_EXCL_START */
706 EXPORT_API int notification_clear(notification_type_e type)
707 {
708         return notification_clear_for_uid(type, getuid());
709 }
710
711 EXPORT_API int notification_op_get_data(notification_op *noti_op, notification_op_data_type_e type,
712                 void *data)
713 {
714         if (noti_op == NULL || data == NULL)
715                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
716
717         switch (type) {
718         case NOTIFICATION_OP_DATA_TYPE:
719                 *((int *)data) = noti_op->type;
720                 break;
721         case NOTIFICATION_OP_DATA_PRIV_ID:
722                 *((int *)data) = noti_op->priv_id;
723                 break;
724         case NOTIFICATION_OP_DATA_NOTI:
725                 *((notification_h *)data) = noti_op->noti;
726                 break;
727         case NOTIFICATION_OP_DATA_EXTRA_INFO_1:
728                 *((int *)data) = noti_op->extra_info_1;
729                 break;
730         case NOTIFICATION_OP_DATA_EXTRA_INFO_2:
731                 *((int *)data) = noti_op->extra_info_2;
732                 break;
733         default:
734                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
735                 break;
736         }
737
738         return NOTIFICATION_ERROR_NONE;
739 }
740 /* LCOV_EXCL_STOP */
741
742 /* LCOV_EXCL_START */
743 EXPORT_API int notification_set_pkgname(notification_h noti,
744                 const char *pkgname)
745 {
746         /* check noti and pkgname are valid data */
747         if (noti == NULL || pkgname == NULL)
748                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
749
750         /* Remove previous caller pkgname */
751         if (noti->caller_pkgname) {
752                 free(noti->caller_pkgname);
753                 noti->caller_pkgname = NULL;
754         }
755
756         noti->caller_pkgname = strdup(pkgname);
757
758         return NOTIFICATION_ERROR_NONE;
759 }
760 /* LCOV_EXCL_STOP */
761
762 /* LCOV_EXCL_START */
763 int notification_delete_all_by_type_for_uid(const char *pkgname,
764                 notification_type_e type, uid_t uid)
765 {
766         int ret = 0;
767         char *caller_pkgname = NULL;
768
769         if (type <= NOTIFICATION_TYPE_NONE || type >= NOTIFICATION_TYPE_MAX)
770                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
771
772         if (pkgname == NULL)
773                 caller_pkgname = notification_get_pkgname_by_pid();
774         else
775                 caller_pkgname = strdup(pkgname);
776
777         ret = notification_ipc_request_delete_multiple(type, caller_pkgname, uid);
778
779         if (caller_pkgname)
780                 free(caller_pkgname);
781
782         return ret;
783 }
784 /* LCOV_EXCL_STOP */
785
786 /* LCOV_EXCL_START */
787 EXPORT_API int notification_delete_all_by_type(const char *pkgname,
788                 notification_type_e type)
789 {
790         return notification_delete_all_by_type_for_uid(pkgname, type, getuid());
791 }
792
793 int notification_delete_by_priv_id_for_uid(const char *pkgname,
794                 notification_type_e type,
795                 int priv_id,
796                 uid_t uid)
797 {
798         int ret = 0;
799         char *caller_pkgname = NULL;
800
801         if (priv_id <= NOTIFICATION_PRIV_ID_NONE)
802                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
803
804         if (pkgname == NULL)
805                 caller_pkgname = notification_get_pkgname_by_pid();
806         else
807                 caller_pkgname = strdup(pkgname);
808
809         ret = notification_ipc_request_delete_single(type, caller_pkgname, priv_id, uid);
810
811         if (caller_pkgname)
812                 free(caller_pkgname);
813
814         return ret;
815 }
816 /* LCOV_EXCL_STOP */
817
818 /* LCOV_EXCL_START */
819 EXPORT_API int notification_delete_by_priv_id(const char *pkgname,
820                 notification_type_e type,
821                 int priv_id)
822 {
823         return notification_delete_by_priv_id_for_uid(pkgname, type, priv_id, getuid());
824 }
825
826 EXPORT_API int notification_set_execute_option(notification_h noti,
827                 notification_execute_type_e type,
828                 const char *text,
829                 const char *key,
830                 bundle *service_handle)
831 {
832         char buf_key[32] = { 0, };
833         char *ret_val = NULL;
834         bundle *b = NULL;
835
836         if (noti == NULL)
837                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
838
839         if (type <= NOTIFICATION_EXECUTE_TYPE_NONE
840                         || type >= NOTIFICATION_EXECUTE_TYPE_MAX)
841                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
842
843         /* Create execute option bundle if does not exist */
844         if (noti->b_execute_option == NULL)
845                 noti->b_execute_option = bundle_create();
846
847         b = noti->b_execute_option;
848
849         /* Save text */
850         if (text != NULL) {
851                 /* Make text key */
852                 snprintf(buf_key, sizeof(buf_key), "text%d", type);
853
854                 /* Check text key exist */
855                 bundle_get_str(b, buf_key, &ret_val);
856                 if (ret_val != NULL)
857                         /* Remove previous data */
858                         bundle_del(b, buf_key);
859
860                 /* Add text data */
861                 bundle_add_str(b, buf_key, text);
862         }
863
864         /* Save key */
865         if (key != NULL) {
866                 /* Make key key */
867                 snprintf(buf_key, sizeof(buf_key), "key%d", type);
868
869                 /* Check key key exist */
870                 bundle_get_str(b, buf_key, &ret_val);
871                 if (ret_val != NULL)
872                         /* Remove previous data */
873                         bundle_del(b, buf_key);
874
875                 /* Add text data */
876                 bundle_add_str(b, buf_key, key);
877         }
878
879         switch ((int)type) {
880         case NOTIFICATION_EXECUTE_TYPE_RESPONDING:
881                 /* Remove previous data if exist */
882                 if (noti->b_service_responding != NULL) {
883                         bundle_free(noti->b_service_responding);
884                         noti->b_service_responding = NULL;
885                 }
886
887                 /* Save service handle */
888                 if (service_handle != NULL)
889                         noti->b_service_responding = bundle_dup(service_handle);
890
891                 break;
892         case NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH:
893                 /* Remove previous data if exist */
894                 if (noti->b_service_single_launch != NULL) {
895                         bundle_free(noti->b_service_single_launch);
896                         noti->b_service_single_launch = NULL;
897                 }
898
899                 /* Save service handle */
900                 if (service_handle != NULL)
901                         noti->b_service_single_launch =
902                                 bundle_dup(service_handle);
903
904                 break;
905         case NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH:
906                 /* Remove previous data if exist */
907                 if (noti->b_service_multi_launch != NULL) {
908                         bundle_free(noti->b_service_multi_launch);
909                         noti->b_service_multi_launch = NULL;
910                 }
911
912                 /* Save service handle */
913                 if (service_handle != NULL)
914                         noti->b_service_multi_launch =
915                                 bundle_dup(service_handle);
916
917                 break;
918         }
919
920         return NOTIFICATION_ERROR_NONE;
921 }
922 /* LCOV_EXCL_STOP */
923
924 /* LCOV_EXCL_START */
925 EXPORT_API int notification_get_id(notification_h noti,
926                 int *group_id, int *priv_id)
927 {
928         /* check noti is valid data */
929         if (noti == NULL)
930                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
931
932         /* Check group_id is valid data */
933         if (group_id) {
934                 /* Set group id */
935                 if (noti->group_id < NOTIFICATION_GROUP_ID_NONE)
936                         *group_id = NOTIFICATION_GROUP_ID_NONE;
937                 else
938                         *group_id = noti->group_id;
939         }
940
941         /* Check priv_id is valid data */
942         if (priv_id)
943                 /* Set priv_id */
944                 *priv_id = noti->priv_id;
945
946         return NOTIFICATION_ERROR_NONE;
947 }
948 /* LCOV_EXCL_STOP */
949
950 /* LCOV_EXCL_START */
951 notification_h notification_load_for_uid(char *pkgname,
952                 int priv_id, uid_t uid)
953 {
954         int ret = 0;
955         notification_h noti = NULL;
956
957         noti = (notification_h)calloc(1, sizeof(struct _notification));
958         if (noti == NULL) {
959                 NOTIFICATION_ERR("NO MEMORY : noti == NULL");
960                 return NULL;
961         }
962
963         ret = notification_ipc_request_load_noti_by_priv_id(noti, pkgname, priv_id, uid);
964         if (ret != NOTIFICATION_ERROR_NONE) {
965                 notification_free(noti);
966                 return NULL;
967         }
968
969         return noti;
970 }
971 /* LCOV_EXCL_STOP */
972
973 /* LCOV_EXCL_START */
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 /* LCOV_EXCL_STOP */
980
981 /* LCOV_EXCL_START */
982 EXPORT_API notification_h notification_new(notification_type_e type,
983                 int group_id, int priv_id)
984 {
985         return notification_create(type);
986 }
987
988 static void _notification_get_text_domain(notification_h noti)
989 {
990 }
991 /* LCOV_EXCL_STOP */
992
993 /* LCOV_EXCL_START */
994 EXPORT_API int notification_get_execute_option(notification_h noti,
995                 notification_execute_type_e type,
996                 const char **text,
997                 bundle **service_handle)
998 {
999         char buf_key[32] = { 0, };
1000         char *ret_val = NULL;
1001         char *get_str = NULL;
1002         bundle *b = NULL;
1003
1004         if (noti == NULL)
1005                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1006
1007         if (type <= NOTIFICATION_EXECUTE_TYPE_NONE
1008                         || type >= NOTIFICATION_EXECUTE_TYPE_MAX)
1009                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1010
1011
1012         switch (type) {
1013         case NOTIFICATION_EXECUTE_TYPE_RESPONDING:
1014                 b = noti->b_service_responding;
1015                 break;
1016         case NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH:
1017                 b = noti->b_service_single_launch;
1018                 break;
1019         case NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH:
1020                 b = noti->b_service_multi_launch;
1021                 break;
1022         default:
1023                 break;
1024         }
1025
1026         if (b != NULL) {
1027                 /* Return text */
1028                 if (text != NULL) {
1029                         /*  Get text domain and dir */
1030                         if (noti->domain == NULL || noti->dir == NULL)
1031                                 _notification_get_text_domain(noti);
1032
1033                         /* Make key */
1034                         snprintf(buf_key, sizeof(buf_key), "key%d", type);
1035
1036                         /* Check key key exist */
1037                         bundle_get_str(b, buf_key, &ret_val);
1038                         if (ret_val != NULL && noti->domain != NULL
1039                                         && noti->dir != NULL) {
1040                                 /* Get application string */
1041                                 bindtextdomain(noti->domain, noti->dir);
1042
1043                                 get_str = dgettext(noti->domain, ret_val);
1044
1045                                 *text = get_str;
1046                         } else if (ret_val != NULL) {
1047                                 /* Get system string */
1048                                 get_str = dgettext("sys_string", ret_val);
1049
1050                                 *text = get_str;
1051                         } else {
1052                                 /* Get basic text */
1053                                 snprintf(buf_key, sizeof(buf_key), "text%d",
1054                                                 type);
1055
1056                                 bundle_get_str(b, buf_key, &ret_val);
1057
1058                                 *text = ret_val;
1059                         }
1060                 }
1061         }
1062
1063         if (service_handle != NULL)
1064                 *service_handle = b;
1065
1066         return NOTIFICATION_ERROR_NONE;
1067 }
1068 /* LCOV_EXCL_STOP */
1069
1070 EXPORT_API int notification_insert_for_uid(notification_h noti,
1071                 int *priv_id, uid_t uid)
1072 {
1073         int ret = 0;
1074         int id = 0;
1075
1076         /* Check noti is vaild data */
1077         if (noti == NULL)
1078                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1079
1080         /* Check noti type is valid type */
1081         if (noti->type <= NOTIFICATION_TYPE_NONE
1082                         || noti->type >= NOTIFICATION_TYPE_MAX)
1083                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1084
1085         noti->uid = uid;
1086         /* Save insert time */
1087         noti->insert_time = time(NULL);
1088         ret = notification_ipc_request_insert(noti, &id);
1089         if (ret != NOTIFICATION_ERROR_NONE)
1090                 return ret;
1091
1092         noti->priv_id = id;
1093         NOTIFICATION_DBG("from master:%d", id);
1094
1095         /* If priv_id is valid data, set priv_id */
1096         if (priv_id != NULL)
1097                 *priv_id = noti->priv_id;
1098
1099         return NOTIFICATION_ERROR_NONE;
1100 }
1101
1102 EXPORT_API int notification_insert(notification_h noti,
1103                 int *priv_id)
1104 {
1105         return notification_insert_for_uid(noti, priv_id, getuid());
1106 }
1107
1108 EXPORT_API int notification_update_async_for_uid(notification_h noti,
1109                 void (*result_cb)(int priv_id, int result, void *data), void *user_data, uid_t uid)
1110 {
1111         int ret = 0;
1112         if (noti == NULL)
1113                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1114
1115         noti->uid = uid;
1116         /* Update insert time ? */
1117         noti->insert_time = time(NULL);
1118         ret = notification_ipc_request_update_async(noti, result_cb, user_data);
1119
1120         return ret;
1121 }
1122
1123 EXPORT_API int notification_update_async(notification_h noti,
1124                 void (*result_cb)(int priv_id, int result, void *data), void *user_data)
1125 {
1126         return notification_update_async_for_uid(noti, result_cb, user_data, getuid());
1127 }
1128
1129 EXPORT_API int notification_register_detailed_changed_cb_for_uid(
1130                 void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
1131                 void *user_data, uid_t uid)
1132 {
1133         GList *noti_cb_list = NULL;
1134         notification_cb_info_s *noti_cb_info_new = NULL;
1135
1136         if (detailed_changed_cb == NULL)
1137                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1138
1139         if (notification_ipc_monitor_init(uid) != NOTIFICATION_ERROR_NONE)
1140                 return NOTIFICATION_ERROR_IO_ERROR;
1141
1142         if (_noti_cb_hash == NULL)
1143                 _noti_cb_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, __free_changed_cb_hash);
1144
1145         noti_cb_info_new = (notification_cb_info_s *)malloc(sizeof(notification_cb_info_s));
1146         if (noti_cb_info_new == NULL) {
1147                 NOTIFICATION_ERR("malloc failed");
1148                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1149         }
1150
1151         noti_cb_info_new->cb_type = NOTIFICATION_CB_DETAILED;
1152         noti_cb_info_new->changed_cb = NULL;
1153         noti_cb_info_new->detailed_changed_cb = detailed_changed_cb;
1154         noti_cb_info_new->data = user_data;
1155
1156         noti_cb_list = g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
1157
1158         if (noti_cb_list == NULL) {
1159                 noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
1160                 g_hash_table_insert(_noti_cb_hash, GUINT_TO_POINTER(uid), noti_cb_list);
1161         } else {
1162                 noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
1163         }
1164
1165         return NOTIFICATION_ERROR_NONE;
1166 }
1167
1168 EXPORT_API int notification_register_detailed_changed_cb(
1169                 void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
1170                 void *user_data)
1171 {
1172         return notification_register_detailed_changed_cb_for_uid(detailed_changed_cb, user_data, getuid());
1173 }
1174
1175 EXPORT_API int notification_unregister_detailed_changed_cb_for_uid(
1176                 void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
1177                 void *user_data, uid_t uid)
1178 {
1179         notification_cb_info_s *noti_cb_info = NULL;
1180         GList *noti_cb_list = NULL;
1181
1182         if (detailed_changed_cb == NULL)
1183                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1184
1185         if (_noti_cb_hash == NULL)
1186                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1187
1188         noti_cb_list = (GList *)g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
1189
1190         if (noti_cb_list == NULL)
1191                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1192
1193         noti_cb_list = g_list_first(noti_cb_list);
1194
1195         for (; noti_cb_list != NULL; noti_cb_list = noti_cb_list->next) {
1196                 noti_cb_info = noti_cb_list->data;
1197                 if (noti_cb_info->detailed_changed_cb == detailed_changed_cb) {
1198                         noti_cb_list = g_list_remove(g_list_first(noti_cb_list), noti_cb_info);
1199
1200                         if (noti_cb_list == NULL)
1201                                 g_hash_table_steal(_noti_cb_hash, GUINT_TO_POINTER(uid));
1202
1203                         if (g_hash_table_size(_noti_cb_hash) == 0)
1204                                 notification_ipc_monitor_fini();
1205
1206                         return NOTIFICATION_ERROR_NONE;
1207                 }
1208         }
1209
1210         return NOTIFICATION_ERROR_INVALID_PARAMETER;
1211 }
1212
1213 EXPORT_API int notification_unregister_detailed_changed_cb(
1214                 void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
1215                 void *user_data)
1216 {
1217         return notification_unregister_detailed_changed_cb_for_uid(detailed_changed_cb, user_data, getuid());
1218 }
1219
1220 /* LCOV_EXCL_START */
1221 EXPORT_API int notification_is_service_ready(void)
1222 {
1223         return notification_ipc_is_master_ready();
1224 }
1225 /* LCOV_EXCL_STOP */
1226
1227 EXPORT_API int notification_set_uid(notification_h noti,
1228                 uid_t uid)
1229 {
1230         if (noti == NULL)
1231                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1232
1233         noti->uid = uid;
1234         return NOTIFICATION_ERROR_NONE;
1235 }
1236
1237 EXPORT_API int notification_get_uid(notification_h noti,
1238                 uid_t *uid)
1239 {
1240         if (noti == NULL || uid == NULL)
1241                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1242
1243         *uid = noti->uid;
1244         return NOTIFICATION_ERROR_NONE;
1245 }
1246
1247 EXPORT_API int notification_post_for_uid(notification_h noti, uid_t uid)
1248 {
1249         int ret = 0;
1250         int id = 0;
1251
1252         /* Check noti is vaild data */
1253         if (noti == NULL)
1254                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1255
1256         /* Check noti type is valid type */
1257         if (noti->type <= NOTIFICATION_TYPE_NONE
1258                         || noti->type >= NOTIFICATION_TYPE_MAX)
1259                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1260
1261         /* Save insert time */
1262         noti->insert_time = time(NULL);
1263         noti->uid = uid;
1264
1265         ret = notification_ipc_request_insert(noti, &id);
1266         if (ret != NOTIFICATION_ERROR_NONE)
1267                 return ret;
1268
1269         noti->priv_id = id;
1270         NOTIFICATION_DBG("from master:%d", id);
1271
1272         return NOTIFICATION_ERROR_NONE;
1273 }
1274
1275 EXPORT_API int notification_update_for_uid(notification_h noti, uid_t uid)
1276 {
1277         int ret;
1278
1279         /* Check noti is valid data */
1280         if (noti != NULL) {
1281                 noti->uid = uid;
1282                 /* Update insert time ? */
1283                 noti->insert_time = time(NULL);
1284                 ret = notification_ipc_request_update(noti);
1285         } else {
1286                 notification_ipc_request_refresh(uid);
1287                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1288         }
1289
1290         return ret;
1291 }
1292
1293 EXPORT_API int notification_delete_for_uid(notification_h noti, uid_t uid)
1294 {
1295         int ret = 0;
1296
1297         if (noti == NULL)
1298                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1299
1300         ret = notification_ipc_request_delete_single(NOTIFICATION_TYPE_NONE, noti->caller_pkgname, noti->priv_id, uid);
1301
1302         return ret;
1303 }
1304
1305 EXPORT_API int notification_delete_all_for_uid(notification_type_e type, uid_t uid)
1306 {
1307         int ret = 0;
1308         char *caller_pkgname = NULL;
1309
1310         if (type <= NOTIFICATION_TYPE_NONE || type >= NOTIFICATION_TYPE_MAX)
1311                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1312
1313         caller_pkgname = notification_get_pkgname_by_pid();
1314
1315         ret = notification_ipc_request_delete_multiple(type, caller_pkgname, uid);
1316
1317         if (caller_pkgname)
1318                 free(caller_pkgname);
1319
1320         return ret;
1321 }
1322
1323 EXPORT_API notification_h notification_load_by_tag_for_uid(const char *tag, uid_t uid)
1324 {
1325         int ret = 0;
1326         notification_h noti = NULL;
1327         char *caller_pkgname = NULL;
1328
1329         if (tag == NULL) {
1330                 NOTIFICATION_ERR("Invalid parameter");
1331                 set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
1332                 return NULL;
1333         }
1334
1335         caller_pkgname = notification_get_pkgname_by_pid();
1336         if (!caller_pkgname) {
1337                 /* LCOV_EXCL_START */
1338                 NOTIFICATION_ERR("Failed to get a package name");
1339                 set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
1340                 return NULL;
1341                 /* LCOV_EXCL_STOP */
1342         }
1343
1344         noti = (notification_h)calloc(1, sizeof(struct _notification));
1345         if (noti == NULL) {
1346                 /* LCOV_EXCL_START */
1347                 NOTIFICATION_ERR("Failed to alloc a new notification");
1348                 set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
1349                 free(caller_pkgname);
1350
1351                 return NULL;
1352                 /* LCOV_EXCL_STOP */
1353         }
1354
1355         ret = notification_ipc_request_load_noti_by_tag(noti, caller_pkgname, (char *)tag, uid);
1356         free(caller_pkgname);
1357
1358         set_last_result(ret);
1359         if (ret != NOTIFICATION_ERROR_NONE) {
1360                 notification_free(noti);
1361                 return NULL;
1362         }
1363
1364         return noti;
1365 }