0453361ce4db262e6db6beb6be268762a02e09de
[platform/core/api/notification.git] / src / notification_ipc.c
1 /*
2  *  libnotification
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Seungtaek Chung <seungtaek.chung@samsung.com>, Mi-Ju Lee <miju52.lee@samsung.com>, Xi Zhichan <zhichan.xi@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <vconf.h>
27 #include <bundle_internal.h>
28
29 #include <notification_ipc.h>
30 #include <notification_db.h>
31 #include <notification_type.h>
32 #include <notification_private.h>
33 #include <notification_debug.h>
34 #include <notification_setting.h>
35 #include <notification_setting_internal.h>
36 #include <notification_internal.h>
37
38 #include <gio/gio.h>
39
40 #define PROVIDER_BUS_NAME "org.tizen.data_provider_service"
41 #define PROVIDER_OBJECT_PATH "/org/tizen/data_provider_service"
42 #define PROVIDER_NOTI_INTERFACE_NAME "org.tizen.data_provider_noti_service"
43
44 #define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
45 #define DBUS_PATH_DBUS "/org/freedesktop/DBus"
46 #define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
47
48 static const gchar *_bus_name = NULL;
49 static GDBusConnection *_gdbus_conn = NULL;
50 static int monitor_id = 0;
51 static int provider_monitor_id = 0;
52 static int is_master_started = 0;
53
54 typedef struct _result_cb_item {
55         void (*result_cb)(int priv_id, int result, void *data);
56         void *data;
57 } result_cb_item;
58
59 typedef struct _task_list task_list;
60 struct _task_list {
61         task_list *prev;
62         task_list *next;
63
64         void (*task_cb) (void *data);
65         void *data;
66 };
67
68 static task_list *g_task_list;
69
70 static int _ipc_monitor_register(void);
71 static int _ipc_monitor_deregister(void);
72 static void _do_deffered_task(void);
73
74 static void _print_noti(notification_h noti) {
75         char *pkgname = NULL;
76         char *text = NULL;
77         char *content = NULL;
78         const char *tag = NULL;
79
80         notification_get_pkgname(noti, &pkgname);
81         notification_get_text(noti, NOTIFICATION_TEXT_TYPE_TITLE, &text);
82         notification_get_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT, &content);
83         notification_get_tag(noti, &tag);
84
85         NOTIFICATION_DBG("client print_noti  pkgname  = %s ", pkgname );
86         NOTIFICATION_DBG("client print_noti  title  = %s ", text );
87         NOTIFICATION_DBG("client print_noti  content  = %s ", content );
88         NOTIFICATION_DBG("client print_noti  tag  = %s ", tag );
89         NOTIFICATION_DBG("client print_noti  priv_id  = %d ", noti->priv_id);
90         NOTIFICATION_DBG("client print_noti  vibration_path  = %s ", noti->vibration_path);
91 }
92
93 static inline char *_string_get(char *string)
94 {
95         if (string == NULL)
96                 return NULL;
97
98         if (string[0] == '\0')
99                 return NULL;
100
101         return string;
102 }
103
104
105 int notification_ipc_is_master_ready(void)
106 {
107         GVariant *result;
108         GError *err = NULL;
109         gboolean name_exist;
110
111         result = g_dbus_connection_call_sync(
112                         _gdbus_conn,
113                         DBUS_SERVICE_DBUS,
114                         DBUS_PATH_DBUS,
115                         DBUS_INTERFACE_DBUS,
116                         "NameHasOwner",
117                         g_variant_new("(s)", PROVIDER_BUS_NAME),
118                         G_VARIANT_TYPE("(b)"),
119                         G_DBUS_CALL_FLAGS_NONE,
120                         -1,
121                         NULL,
122                         &err);
123
124         if (err || (result == NULL)) {
125                 if (err) {
126                 NOTIFICATION_ERR("No reply. error = %s", err->message);
127                         g_error_free(err);
128                 }
129                 is_master_started = 0;
130         } else {
131                 g_variant_get(result, "(b)", &name_exist);
132
133                 if (!name_exist) {
134                         NOTIFICATION_ERR("Name not exist %s", PROVIDER_BUS_NAME);
135                         NOTIFICATION_ERR("the master has been stopped");
136                         is_master_started = 0;
137                 } else {
138                         NOTIFICATION_DBG("the master has been started");
139                         is_master_started = 1;
140                 }
141         }
142
143         if(result)
144                 g_variant_unref(result);
145
146         return is_master_started;
147 }
148
149 /* TODO: dbus activation isn't enough ? */
150 /*
151  * store tasks when daemon stopped
152  */
153 int notification_ipc_add_deffered_task(
154                 void (*deferred_task_cb)(void *data),
155                 void *user_data)
156 {
157         task_list *list;
158         task_list *list_new;
159
160         list_new =
161             (task_list *) malloc(sizeof(task_list));
162
163         if (list_new == NULL)
164                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
165
166         list_new->next = NULL;
167         list_new->prev = NULL;
168
169         list_new->task_cb = deferred_task_cb;
170         list_new->data = user_data;
171
172         if (g_task_list == NULL) {
173                 g_task_list = list_new;
174         } else {
175                 list = g_task_list;
176
177                 while (list->next != NULL)
178                         list = list->next;
179
180                 list->next = list_new;
181                 list_new->prev = list;
182         }
183         return NOTIFICATION_ERROR_NONE;
184 }
185
186 int notification_ipc_del_deffered_task(
187                 void (*deferred_task_cb)(void *data))
188 {
189         task_list *list_del;
190         task_list *list_prev;
191         task_list *list_next;
192
193         list_del = g_task_list;
194
195         if (list_del == NULL)
196                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
197
198         while (list_del->prev != NULL)
199                 list_del = list_del->prev;
200
201         do {
202                 if (list_del->task_cb == deferred_task_cb) {
203                         list_prev = list_del->prev;
204                         list_next = list_del->next;
205
206                         if (list_prev == NULL)
207                                 g_task_list = list_next;
208                         else
209                                 list_prev->next = list_next;
210
211                         if (list_next == NULL) {
212                                 if (list_prev != NULL)
213                                         list_prev->next = NULL;
214                         } else {
215                                 list_next->prev = list_prev;
216                         }
217
218                         free(list_del);
219                         return NOTIFICATION_ERROR_NONE;
220                 }
221                 list_del = list_del->next;
222         } while (list_del != NULL);
223
224         return NOTIFICATION_ERROR_INVALID_PARAMETER;
225 }
226
227 static void _do_deffered_task(void)
228 {
229         task_list *list_do;
230         task_list *list_temp;
231
232         if (g_task_list == NULL)
233                 return;
234
235         list_do = g_task_list;
236         g_task_list = NULL;
237
238         while (list_do->prev != NULL)
239                 list_do = list_do->prev;
240
241         while (list_do != NULL) {
242                 if (list_do->task_cb != NULL) {
243                         list_do->task_cb(list_do->data);
244                         NOTIFICATION_DBG("called:%p", list_do->task_cb);
245                 }
246                 list_temp = list_do->next;
247                 free(list_do);
248                 list_do = list_temp;
249         }
250 }
251
252 /*!
253  * functions to create operation list
254  */
255 static notification_op *_ipc_create_op(notification_op_type_e type,
256                 int num_op, int *list_priv_id, int num_priv_id, notification_h *noti_list)
257 {
258         int i;
259         notification_op *op_list;
260
261         if (num_op <= 0)
262                 return NULL;
263
264         op_list = (notification_op *)malloc(sizeof(notification_op) * num_op);
265
266         if (op_list == NULL) {
267                 NOTIFICATION_ERR("malloc failed");
268                 return NULL;
269         }
270
271         memset(op_list, 0x0, sizeof(notification_op) * num_op);
272
273         for (i = 0; i < num_op; i++) {
274                 (op_list + i)->type = type;
275                 if (list_priv_id != NULL)
276                         (op_list + i)->priv_id = *(list_priv_id + i);
277                 if (noti_list != NULL)
278                         (op_list + i)->noti = *(noti_list + i);
279         }
280
281         return op_list;
282 }
283
284 /*!
285  * utility functions creating notification packet
286  */
287 static inline char *_dup_string(const char *string)
288 {
289         char *ret;
290
291         if (string == NULL)
292                 return NULL;
293         if (string[0] == '\0')
294                 return NULL;
295
296         ret = strdup(string);
297         if (!ret)
298                 NOTIFICATION_ERR("Error: %s\n", strerror(errno));
299
300         return ret;
301 }
302
303 static inline bundle *_create_bundle_from_bundle_raw(bundle_raw *string)
304 {
305         if (string == NULL)
306                 return NULL;
307         if (string[0] == '\0')
308                 return NULL;
309
310         return bundle_decode(string, strlen((char *)string));
311 }
312
313 static void _add_noti_notify(GVariant *parameters)
314 {
315         notification_h noti;
316         notification_op *noti_op;
317         GVariant *body = NULL;
318
319         NOTIFICATION_DBG("add noti notify");
320         noti = notification_create(NOTIFICATION_TYPE_NOTI);
321         if (!noti) {
322                 NOTIFICATION_ERR("failed to create a notification");
323                 return;
324         }
325
326         g_variant_get(parameters, "(v)", &body);
327         notification_ipc_make_noti_from_gvariant(noti, body);
328         _print_noti(noti);
329         if (noti->flags_for_property & NOTIFICATION_PROP_DISABLE_UPDATE_ON_INSERT) {
330                 NOTIFICATION_ERR("disable changed callback %d", noti->flags_for_property);
331                 /* Disable changed cb */
332         } else {
333                 /* Enable changed cb */
334                 noti_op = _ipc_create_op(NOTIFICATION_OP_INSERT, 1, &(noti->priv_id), 1, &noti);
335
336                 if (noti_op != NULL) {
337                         notification_call_changed_cb(noti_op, 1);
338                         free(noti_op);
339                 }
340         }
341         notification_free(noti);
342 }
343
344 static void _update_noti_notify(GVariant *parameters)
345 {
346         notification_h noti;
347         notification_op *noti_op;
348         GVariant *body = NULL;
349
350         noti = notification_create(NOTIFICATION_TYPE_NOTI);
351         if (!noti) {
352                 NOTIFICATION_ERR("failed to create a notification");
353                 return;
354         }
355         g_variant_get(parameters, "(v)", &body);
356         notification_ipc_make_noti_from_gvariant(noti, body);
357         _print_noti(noti);
358
359         noti_op = _ipc_create_op(NOTIFICATION_OP_UPDATE, 1, &(noti->priv_id), 1, &noti);
360         if (noti_op != NULL) {
361                 notification_call_changed_cb(noti_op, 1);
362                 free(noti_op);
363         }
364         notification_free(noti);
365 }
366
367 static void _refresh_noti_notify(GVariant *parameters)
368 {
369         notification_op *noti_op = _ipc_create_op(NOTIFICATION_OP_REFRESH, 1, NULL, 0, NULL);
370
371         if (noti_op != NULL) {
372                 notification_call_changed_cb(noti_op, 1);
373                 free(noti_op);
374         }
375 }
376
377 static void _delete_single_notify(GVariant *parameters)
378 {
379         int num_deleted;
380         int priv_id;
381         notification_op *noti_op;
382
383         /* num_deleted ?? */
384         g_variant_get(parameters, "(ii)", &num_deleted, &priv_id);
385
386         noti_op = _ipc_create_op(NOTIFICATION_OP_DELETE, 1, &priv_id, 1, NULL);
387         if (noti_op != NULL) {
388                 notification_call_changed_cb(noti_op, 1);
389                 free(noti_op);
390         }
391 }
392
393 static void _delete_multiple_notify(GVariant *parameters)
394 {
395         int buf[100] = {0,};
396         int idx = 0;
397         notification_op *noti_op;
398         GVariantIter *iter;
399
400         g_variant_get(parameters, "(a(i))", &iter);
401         while (g_variant_iter_loop(iter, "(i)", &buf[idx])) {
402                 NOTIFICATION_DBG("delete_noti_multiple priv_id : %d", buf[idx]);
403                 idx++;
404         }
405         g_variant_iter_free(iter);
406
407         NOTIFICATION_DBG("data num deleted:%d", idx);
408         noti_op = _ipc_create_op(NOTIFICATION_OP_DELETE, idx, buf, idx, NULL);
409
410         if (noti_op == NULL) {
411                 NOTIFICATION_ERR("_ipc_create_op failed");
412                 return;
413         }
414         notification_call_changed_cb(noti_op, idx);
415         free(noti_op);
416 }
417
418 static void _handle_noti_notify(GDBusConnection *connection,
419                 const gchar     *sender_name,
420                 const gchar     *object_path,
421                 const gchar     *interface_name,
422                 const gchar     *signal_name,
423                 GVariant        *parameters,
424                 gpointer         user_data)
425 {
426         NOTIFICATION_DBG("signal_name: %s", signal_name);
427
428         if (g_strcmp0(signal_name, "add_noti_notify") == 0)
429                 _add_noti_notify(parameters);
430         else if (g_strcmp0(signal_name, "update_noti_notify") == 0)
431                 _update_noti_notify(parameters);
432         else if (g_strcmp0(signal_name, "delete_single_notify") == 0)
433                 _delete_single_notify(parameters);
434         else if (g_strcmp0(signal_name, "delete_multiple_notify") == 0)
435                 _delete_multiple_notify(parameters);
436         else if (g_strcmp0(signal_name, "refresh_noti_notify") == 0)
437                 _refresh_noti_notify(parameters);
438 }
439
440
441 static int _dbus_signal_init()
442 {
443         int id;
444         int ret = NOTIFICATION_ERROR_NONE;
445
446         if (monitor_id == 0) {
447                 id = g_dbus_connection_signal_subscribe(_gdbus_conn,
448                                 PROVIDER_BUS_NAME,
449                                 PROVIDER_NOTI_INTERFACE_NAME,   /*      interface */
450                                 NULL,                           /*      member */
451                                 PROVIDER_OBJECT_PATH,           /*      path */
452                                 NULL,                           /*      arg0 */
453                                 G_DBUS_SIGNAL_FLAGS_NONE,
454                                 _handle_noti_notify,
455                                 NULL,
456                                 NULL);
457
458                 NOTIFICATION_DBG("subscribe id : %d", id);
459                 if (id == 0) {
460                         ret = NOTIFICATION_ERROR_IO_ERROR;
461                         NOTIFICATION_ERR("Failed to _register_noti_dbus_interface");
462                 } else {
463                         monitor_id = id;
464                         ret = NOTIFICATION_ERROR_NONE;
465                 }
466         }
467         return ret;
468 }
469
470
471 static int _dbus_init()
472 {
473         int ret = NOTIFICATION_ERROR_NONE;
474         GError *error = NULL;
475
476         if (_gdbus_conn == NULL) {
477                 _gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
478
479                 if (_gdbus_conn == NULL) {
480                         if (error != NULL) {
481                                 NOTIFICATION_ERR("Failed to get dbus [%s]", error->message);
482                                 g_error_free(error);
483                         }
484                         return NOTIFICATION_ERROR_IO_ERROR;
485                 }
486                 _bus_name = g_dbus_connection_get_unique_name(_gdbus_conn);
487                 NOTIFICATION_DBG("bus name : %s", _bus_name);
488
489                 notification_error_quark();
490
491                 ret = NOTIFICATION_ERROR_NONE;
492         }
493         return ret;
494 }
495
496 static int _send_sync_noti(GVariant *body, GDBusMessage **reply, char *cmd)
497 {
498         int ret = NOTIFICATION_ERROR_NONE;
499         GError *err = NULL;
500         GDBusMessage *msg;
501
502         msg = g_dbus_message_new_method_call(
503                         PROVIDER_BUS_NAME,
504                         PROVIDER_OBJECT_PATH,
505                         PROVIDER_NOTI_INTERFACE_NAME,
506                         cmd);
507         if (!msg) {
508                 NOTIFICATION_ERR("Can't allocate new method call");
509                 if (body)
510                         g_variant_unref(body);
511                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
512         }
513
514         if (body != NULL)
515                 g_dbus_message_set_body(msg, body);
516
517         *reply = g_dbus_connection_send_message_with_reply_sync(
518                         _gdbus_conn,
519                         msg,
520                         G_DBUS_SEND_MESSAGE_FLAGS_NONE,
521                         -1,
522                         NULL,
523                         NULL,
524                         &err);
525
526         g_object_unref(msg);
527
528         if (!*reply) {
529                 ret = NOTIFICATION_ERROR_SERVICE_NOT_READY;
530                 if (err != NULL) {
531                         NOTIFICATION_ERR("No reply. cmd = %s,  error = %s", cmd, err->message);
532                         if (err->code == G_DBUS_ERROR_ACCESS_DENIED)
533                                 ret = NOTIFICATION_ERROR_PERMISSION_DENIED;
534                         g_error_free(err);
535                 }
536                 return ret;
537         }
538
539         if (g_dbus_message_to_gerror(*reply, &err)) {
540                 ret = err->code;
541                 NOTIFICATION_ERR("_send_sync_noti cmd = %s, error %s", cmd, err->message);
542                 g_error_free(err);
543                 return ret;
544         }
545         NOTIFICATION_DBG("_send_sync_noti done !!");
546         return NOTIFICATION_ERROR_NONE;
547
548 }
549
550 static void _send_message_with_reply_async_cb(GDBusConnection *connection,
551                 GAsyncResult *res,
552                 gpointer user_data)
553 {
554         GVariant *body;
555         int result = NOTIFICATION_ERROR_NONE;
556         int priv_id;
557         GDBusMessage *reply = NULL;
558         GError *err = NULL;
559         result_cb_item *cb_item = (result_cb_item *)user_data;
560
561         if (cb_item == NULL) {
562                 NOTIFICATION_ERR("Failed to get a callback item");
563                 return;
564         }
565
566         reply = g_dbus_connection_send_message_with_reply_finish(
567                         connection,
568                         res,
569                         &err);
570
571         if (!reply) {
572                 if (err != NULL) {
573                         NOTIFICATION_ERR("No reply. error = %s", err->message);
574                         g_error_free(err);
575                 }
576                 result = NOTIFICATION_ERROR_SERVICE_NOT_READY;
577
578         } else if (g_dbus_message_to_gerror(reply, &err)) {
579                 result = err->code;
580                 g_error_free(err);
581                 NOTIFICATION_ERR("_send_async_noti error %s", err->message);
582         }
583
584         NOTIFICATION_DBG("_send_async_noti done !![%d]", result);
585
586         if (result == NOTIFICATION_ERROR_NONE) {
587                 body = g_dbus_message_get_body(reply);
588                 g_variant_get(body, "(i)", &priv_id);
589
590                 if (cb_item->result_cb)
591                         cb_item->result_cb(priv_id, result, cb_item->data);
592
593         } else {
594                 if (cb_item->result_cb)
595                         cb_item->result_cb(NOTIFICATION_PRIV_ID_NONE, result, cb_item->data);
596         }
597
598         if (reply)
599                 g_object_unref(reply);
600         free(cb_item);
601 }
602
603 static int _send_async_noti(GVariant *body, result_cb_item *cb_item, char *cmd)
604 {
605         GDBusMessage *msg;
606
607         msg = g_dbus_message_new_method_call(
608                         PROVIDER_BUS_NAME,
609                         PROVIDER_OBJECT_PATH,
610                         PROVIDER_NOTI_INTERFACE_NAME,
611                         cmd);
612         if (!msg) {
613                 NOTIFICATION_ERR("Can't allocate new method call");
614                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
615         }
616
617         if (body != NULL)
618                 g_dbus_message_set_body(msg, body);
619
620         g_dbus_connection_send_message_with_reply(
621                         _gdbus_conn,
622                         msg,
623                         G_DBUS_SEND_MESSAGE_FLAGS_NONE,
624                         -1,
625                         NULL,
626                         NULL,
627                         (GAsyncReadyCallback)_send_message_with_reply_async_cb,
628                         cb_item);
629
630         NOTIFICATION_DBG("_send_async_noti done !!");
631
632         g_object_unref(msg);
633         return NOTIFICATION_ERROR_NONE;
634 }
635
636 int notification_ipc_request_insert(notification_h noti, int *priv_id)
637 {
638         int result;
639         int id;
640         GDBusMessage *reply = NULL;
641         GVariant *body;
642         GVariant *reply_body;
643
644         result = _dbus_init();
645         if (result != NOTIFICATION_ERROR_NONE) {
646                 NOTIFICATION_ERR("Can't init dbus %d", result);
647                 return result;
648         }
649
650         /* Initialize private ID */
651         noti->priv_id = NOTIFICATION_PRIV_ID_NONE;
652         noti->group_id = NOTIFICATION_GROUP_ID_NONE;
653         noti->internal_group_id = NOTIFICATION_GROUP_ID_NONE;
654
655         _print_noti(noti);
656         body = notification_ipc_make_gvariant_from_noti(noti);
657         if (body == NULL) {
658                 NOTIFICATION_ERR("cannot make gvariant");
659                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
660         }
661
662         result = _send_sync_noti(body, &reply, "add_noti");
663         NOTIFICATION_DBG("_send_sync_noti %d", result);
664
665         if (result == NOTIFICATION_ERROR_NONE) {
666                 reply_body = g_dbus_message_get_body(reply);
667                 g_variant_get(reply_body, "(i)", &id);
668
669                 if (priv_id != NULL)
670                         *priv_id = id;
671         }
672
673         if(reply)
674                 g_object_unref(reply);
675
676         NOTIFICATION_DBG("notification_ipc_request_insert done [priv_id : %d, result: %d]", *priv_id, result);
677         return result;
678 }
679
680 int notification_ipc_request_update(notification_h noti)
681 {
682         int result;
683         int priv_id;
684
685         GDBusMessage *reply = NULL;
686         GVariant *body;
687         GVariant *reply_body;
688
689         result = _dbus_init();
690         if (result != NOTIFICATION_ERROR_NONE) {
691                 NOTIFICATION_ERR("Can't init dbus %d", result);
692                 return result;
693         }
694
695         body = notification_ipc_make_gvariant_from_noti(noti);
696         if (body == NULL) {
697                 NOTIFICATION_ERR("cannot make gvariant");
698                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
699         }
700
701         result = _send_sync_noti(body, &reply, "update_noti");
702         if (result == NOTIFICATION_ERROR_NONE) {
703                 reply_body = g_dbus_message_get_body(reply);
704                 g_variant_get(reply_body, "(i)", &priv_id);
705         }
706
707         if(reply)
708                 g_object_unref(reply);
709
710         NOTIFICATION_DBG("notification_ipc_request_update done [result: %d, priv_id :%d]", result, priv_id);
711         return result;
712 }
713
714 int notification_ipc_request_update_async(notification_h noti,
715                 void (*result_cb)(int priv_id, int result, void *data), void *user_data)
716 {
717         int result;
718         result_cb_item *cb_item;
719         GVariant *body;
720
721         result = _dbus_init();
722         if (result != NOTIFICATION_ERROR_NONE) {
723                 NOTIFICATION_ERR("Can't init dbus %d", result);
724                 return result;
725         }
726
727         cb_item = calloc(1, sizeof(result_cb_item));
728         if (cb_item == NULL)
729                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
730
731         cb_item->result_cb = result_cb;
732         cb_item->data = user_data;
733
734         body = notification_ipc_make_gvariant_from_noti(noti);
735         if (body == NULL) {
736                 NOTIFICATION_ERR("cannot make gvariant");
737                 free(cb_item);
738                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
739         }
740
741         result = _send_async_noti(body, cb_item, "update_noti");
742         NOTIFICATION_DBG("notification_ipc_request_update_async done [result: %d]", result);
743
744         if (result != NOTIFICATION_ERROR_NONE) {
745                 free(cb_item);
746                 cb_item = NULL;
747         }
748
749         g_variant_unref(body);
750
751         return result;
752 }
753
754 int notification_ipc_request_refresh(void)
755 {
756         int result;
757         GDBusMessage *reply = NULL;
758         GVariant *body;
759
760         result = _dbus_init();
761         if (result != NOTIFICATION_ERROR_NONE) {
762                 NOTIFICATION_ERR("Can't init dbus %d", result);
763                 return result;
764         }
765
766         body = g_variant_new("(i)", NOTIFICATION_OP_REFRESH);
767         result = _send_sync_noti(body, &reply, "refresh_noti");
768
769         if(reply)
770                 g_object_unref(reply);
771
772         NOTIFICATION_ERR("notification_ipc_request_refresh done [result: %d]", result);
773         return result;
774 }
775
776 int notification_ipc_request_delete_single(notification_type_e type, char *pkgname, int priv_id)
777 {
778         int result;
779         int id;
780         GDBusMessage *reply = NULL;
781         GVariant *body;
782         GVariant *reply_body;
783
784         result = _dbus_init();
785         if (result != NOTIFICATION_ERROR_NONE) {
786                 NOTIFICATION_ERR("Can't init dbus %d", result);
787                 return result;
788         }
789
790         body = g_variant_new("(si)", pkgname, priv_id);
791         result = _send_sync_noti(body, &reply, "del_noti_single");
792
793         if (result == NOTIFICATION_ERROR_NONE) {
794                 reply_body = g_dbus_message_get_body(reply);
795                 g_variant_get(reply_body, "(i)", &id);
796         }
797
798         if(reply)
799                 g_object_unref(reply);
800
801         NOTIFICATION_ERR("notification_ipc_request_delete_single done [result: %d]", result);
802         return result;
803 }
804
805 int notification_ipc_request_delete_multiple(notification_type_e type, char *pkgname)
806 {
807         int result;
808         int num_deleted;
809         GVariant *body;
810         GVariant *reply_body;
811         GDBusMessage *reply = NULL;
812
813         result = _dbus_init();
814         if (result != NOTIFICATION_ERROR_NONE) {
815                 NOTIFICATION_ERR("Can't init dbus %d", result);
816                 return result;
817         }
818
819         body = g_variant_new("(si)", pkgname, type);
820         result = _send_sync_noti(body, &reply, "del_noti_multiple");
821
822         if (result == NOTIFICATION_ERROR_NONE) {
823                 reply_body = g_dbus_message_get_body(reply);
824                 g_variant_get(reply_body, "(i)", &num_deleted);
825                 NOTIFICATION_ERR("num deleted:%d", num_deleted);
826         }
827
828         if(reply)
829                 g_object_unref(reply);
830
831         return result;
832 }
833
834 int notification_ipc_request_load_noti_by_tag(notification_h noti, const char *pkgname, const char *tag)
835 {
836         int result;
837         GDBusMessage *reply = NULL;
838         GVariant *body;
839         GVariant *reply_body;
840         GVariant *noti_body;
841
842         result = _dbus_init();
843         if (result != NOTIFICATION_ERROR_NONE) {
844                 NOTIFICATION_ERR("Can't init dbus %d", result);
845                 return result;
846         }
847
848         body = g_variant_new("(ss)", pkgname, tag);
849         result = _send_sync_noti(body, &reply, "load_noti_by_tag");
850
851         if (result == NOTIFICATION_ERROR_NONE) {
852                 reply_body = g_dbus_message_get_body(reply);
853                 g_variant_get(reply_body, "(v)", &noti_body);
854
855                 notification_ipc_make_noti_from_gvariant(noti, noti_body);
856                 g_variant_unref(noti_body);
857                 _print_noti(noti);
858
859         }
860
861         if(reply)
862                 g_object_unref(reply);
863
864         NOTIFICATION_DBG("notification_ipc_request_load_noti_by_tag done [result: %d]", result);
865         return result;
866 }
867
868 int notification_ipc_request_load_noti_by_priv_id(notification_h noti, const char *pkgname, int priv_id)
869 {
870         int result;
871         GDBusMessage *reply = NULL;
872         GVariant *body;
873         GVariant *reply_body;
874         GVariant *noti_body;
875
876         result = _dbus_init();
877         if (result != NOTIFICATION_ERROR_NONE) {
878                 NOTIFICATION_ERR("Can't init dbus %d", result);
879                 return result;
880         }
881
882         body = g_variant_new("(si)", pkgname, priv_id);
883         result = _send_sync_noti(body, &reply, "load_noti_by_priv_id");
884
885         if (result == NOTIFICATION_ERROR_NONE) {
886                 reply_body = g_dbus_message_get_body(reply);
887                 g_variant_get(reply_body, "(v)", &noti_body);
888
889                 notification_ipc_make_noti_from_gvariant(noti, noti_body);
890                 g_variant_unref(noti_body);
891                 _print_noti(noti);
892         }
893
894         if(reply)
895                 g_object_unref(reply);
896
897         NOTIFICATION_DBG("notification_ipc_request_load_noti_by_priv_id done [result: %d]", result);
898         return result;
899 }
900
901 int notification_ipc_request_get_count(notification_type_e type,
902                     const char *pkgname, int group_id, int priv_id, int *count)
903 {
904         int result;
905         GDBusMessage *reply = NULL;
906         GVariant *body;
907         GVariant *reply_body;
908         int re_count;
909
910         result = _dbus_init();
911         if (result != NOTIFICATION_ERROR_NONE) {
912                 NOTIFICATION_ERR("Can't init dbus %d", result);
913                 return result;
914         }
915
916         body = g_variant_new("(isii)", type, pkgname, group_id, priv_id);
917         result = _send_sync_noti(body, &reply, "get_noti_count");
918
919         if (result == NOTIFICATION_ERROR_NONE) {
920                 reply_body = g_dbus_message_get_body(reply);
921                 g_variant_get(reply_body, "(i)", &re_count);
922
923                 *count = re_count;
924                 NOTIFICATION_DBG("noti count [%d]", re_count);
925         }
926
927         if(reply)
928                 g_object_unref(reply);
929
930         NOTIFICATION_DBG("notification_ipc_request_get_count done [result: %d]", result);
931         return result;
932 }
933
934 int notification_ipc_request_load_noti_grouping_list(notification_type_e type, int count,
935                 notification_list_h *list)
936 {
937         int result;
938         GDBusMessage *reply = NULL;
939         GVariant *body;
940         GVariant *reply_body;
941         GVariant *iter_body;
942         GVariantIter *iter;
943         notification_h noti;
944         GVariant *noti_body;
945
946         result = _dbus_init();
947         if (result != NOTIFICATION_ERROR_NONE) {
948                 NOTIFICATION_ERR("Can't init dbus %d", result);
949                 return result;
950         }
951
952         body = g_variant_new("(ii)", type, count);
953         result = _send_sync_noti(body, &reply, "load_noti_grouping_list");
954
955         if (result == NOTIFICATION_ERROR_NONE) {
956                 reply_body = g_dbus_message_get_body(reply);
957                 g_variant_get(reply_body, "(a(v))", &iter);
958
959                 while (g_variant_iter_loop(iter, "(v)", &iter_body)) {
960                         noti = notification_create(NOTIFICATION_TYPE_NOTI);
961                         g_variant_get(iter_body, "(v)", &noti_body);
962                         notification_ipc_make_noti_from_gvariant(noti, noti_body);
963                         _print_noti(noti);
964                         *list = notification_list_append(*list, noti);
965                 }
966                 g_variant_iter_free(iter);
967         }
968
969         if(reply)
970                 g_object_unref(reply);
971
972         NOTIFICATION_DBG("notification_ipc_request_load_noti_grouping_list done [result: %d]", result);
973         return result;
974 }
975
976 int notification_ipc_request_load_noti_detail_list(const char *pkgname,
977                 int group_id,
978                 int priv_id,
979                 int count,
980                 notification_list_h *list)
981 {
982         int result;
983         GDBusMessage *reply = NULL;
984         GVariant *body;
985         GVariant *reply_body;
986         GVariant *iter_body;
987         GVariantIter *iter;
988         notification_h noti;
989         GVariant *noti_body;
990
991         result = _dbus_init();
992         if (result != NOTIFICATION_ERROR_NONE) {
993                 NOTIFICATION_ERR("Can't init dbus %d", result);
994                 return result;
995         }
996
997         body = g_variant_new("(siii)", pkgname, group_id, priv_id, count);
998         result = _send_sync_noti(body, &reply, "load_noti_detail_list");
999
1000         if (result == NOTIFICATION_ERROR_NONE) {
1001                 reply_body = g_dbus_message_get_body(reply);
1002                 g_variant_get(reply_body, "(a(v))", &iter);
1003
1004                 while (g_variant_iter_loop(iter, "(v)", &iter_body)) {
1005                         noti = notification_create(NOTIFICATION_TYPE_NOTI);
1006                         g_variant_get(iter_body, "(v)", &noti_body);
1007                         notification_ipc_make_noti_from_gvariant(noti, noti_body);
1008                         _print_noti(noti);
1009                         *list = notification_list_append(*list, noti);
1010                 }
1011                 g_variant_iter_free(iter);
1012         }
1013
1014         if(reply)
1015                 g_object_unref(reply);
1016
1017         NOTIFICATION_DBG("notification_ipc_request_load_noti_detail_list done [result: %d]", result);
1018         return result;
1019 }
1020
1021 int notification_ipc_request_get_setting_array(
1022                 notification_setting_h *setting_array,
1023                 int *count)
1024 {
1025         int result;
1026         GDBusMessage *reply = NULL;
1027         GVariant *reply_body;
1028         GVariant *iter_body;
1029         GVariantIter *iter;
1030         int setting_cnt;
1031         notification_setting_h result_setting_array;
1032         notification_setting_h temp;
1033         int setting_idx;
1034
1035         result = _dbus_init();
1036         if (result != NOTIFICATION_ERROR_NONE) {
1037                 NOTIFICATION_ERR("Can't init dbus %d", result);
1038                 return result;
1039         }
1040
1041         result = _send_sync_noti(NULL, &reply, "get_setting_array");
1042
1043         if (result == NOTIFICATION_ERROR_NONE) {
1044                 reply_body = g_dbus_message_get_body(reply);
1045                 g_variant_get(reply_body, "(ia(v))", &setting_cnt, &iter);
1046
1047                 NOTIFICATION_DBG("get setting arr cnt: %d", setting_cnt);
1048                 result_setting_array = (struct notification_setting *)malloc(sizeof(struct notification_setting) * setting_cnt);
1049                 if (result_setting_array == NULL) {
1050                         NOTIFICATION_ERR("malloc failed");
1051                         g_object_unref(reply);
1052                         g_variant_iter_free(iter);
1053                         return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1054                 }
1055
1056                 setting_idx = 0;
1057                 while (g_variant_iter_loop(iter, "(v)", &iter_body)) {
1058                         temp = result_setting_array + setting_idx;
1059                         notification_ipc_make_setting_from_gvariant(temp, iter_body);
1060                         setting_idx++;
1061                 }
1062
1063                 *count = setting_cnt;
1064                 *setting_array = result_setting_array;
1065                 g_variant_iter_free(iter);
1066         }
1067
1068         if(reply)
1069                 g_object_unref(reply);
1070
1071         NOTIFICATION_DBG("notification_ipc_request_get_setting_array done [result: %d]", result);
1072         return result;
1073 }
1074
1075 int notification_ipc_request_get_setting_by_package_name(
1076                 const char *package_name, notification_setting_h *setting)
1077 {
1078         int result;
1079         GDBusMessage *reply = NULL;
1080         GVariant *body;
1081         GVariant *reply_body;
1082         GVariant *setting_body;
1083         notification_setting_h result_setting;
1084
1085         result = _dbus_init();
1086         if (result != NOTIFICATION_ERROR_NONE) {
1087                 NOTIFICATION_ERR("Can't init dbus %d", result);
1088                 return result;
1089         }
1090
1091         body = g_variant_new("(s)", package_name);
1092         result = _send_sync_noti(body, &reply, "get_setting_by_package_name");
1093
1094         if (result == NOTIFICATION_ERROR_NONE) {
1095                 reply_body = g_dbus_message_get_body(reply);
1096                 g_variant_get(reply_body, "(v)", &setting_body);
1097
1098                 result_setting = (struct notification_setting *)malloc(sizeof(struct notification_setting));
1099                 if (result_setting == NULL) {
1100                         NOTIFICATION_ERR("malloc failed");
1101                         g_object_unref(reply);
1102                         g_variant_unref(body);
1103                         return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1104                 }
1105                 notification_ipc_make_setting_from_gvariant(result_setting, setting_body);
1106
1107                 *setting = result_setting;
1108                 g_variant_unref(setting_body);
1109         }
1110
1111         if(reply)
1112                 g_object_unref(reply);
1113
1114         NOTIFICATION_DBG("notification_ipc_request_get_setting_by_package_name done [result: %d]", result);
1115         return result;
1116 }
1117
1118 int notification_ipc_request_load_system_setting(notification_system_setting_h *setting)
1119 {
1120         int result;
1121         GDBusMessage *reply = NULL;
1122         GVariant *setting_body;
1123         GVariant *reply_body;
1124         notification_system_setting_h result_setting;
1125
1126         result = _dbus_init();
1127         if (result != NOTIFICATION_ERROR_NONE) {
1128                 NOTIFICATION_ERR("Can't init dbus %d", result);
1129                 return result;
1130         }
1131
1132         result = _send_sync_noti(NULL, &reply, "load_system_setting");
1133
1134         if (result == NOTIFICATION_ERROR_NONE) {
1135                 reply_body = g_dbus_message_get_body(reply);
1136                 g_variant_get(reply_body, "(v)", &setting_body);
1137
1138                 result_setting = (struct notification_system_setting *)malloc(sizeof(struct notification_system_setting));
1139                 if (result_setting == NULL) {
1140                         NOTIFICATION_ERR("malloc failed");
1141                         g_object_unref(reply);
1142                         return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1143                 }
1144                 notification_ipc_make_system_setting_from_gvariant(result_setting, setting_body);
1145
1146                 *setting = result_setting;
1147                 g_variant_unref(setting_body);
1148         }
1149
1150         if(reply)
1151                 g_object_unref(reply);
1152
1153         NOTIFICATION_DBG("notification_ipc_request_load_system_setting done [result: %d]", result);
1154         return result;
1155 }
1156
1157 int notification_ipc_update_setting(notification_setting_h setting)
1158 {
1159         int result;
1160         GDBusMessage *reply = NULL;
1161         GVariant *body;
1162
1163         result = _dbus_init();
1164         if (result != NOTIFICATION_ERROR_NONE) {
1165                 NOTIFICATION_ERR("Can't init dbus %d", result);
1166                 return result;
1167         }
1168
1169         body = g_variant_new("(siii)",
1170                         setting->package_name,
1171                         (int)(setting->allow_to_notify),
1172                         (int)(setting->do_not_disturb_except),
1173                         (int)(setting->visibility_class));
1174
1175         result = _send_sync_noti(body, &reply, "update_noti_setting");
1176
1177         if(reply)
1178                 g_object_unref(reply);
1179
1180         NOTIFICATION_DBG("notification_ipc_update_setting done [result: %d]", result);
1181         return result;
1182 }
1183
1184 int notification_ipc_update_system_setting(notification_system_setting_h system_setting)
1185 {
1186         int result;
1187         GDBusMessage *reply = NULL;
1188         GVariant *body;
1189
1190         result = _dbus_init();
1191         if (result != NOTIFICATION_ERROR_NONE) {
1192                 NOTIFICATION_ERR("Can't init dbus %d", result);
1193                 return result;
1194         }
1195
1196         body = g_variant_new("(ii)",
1197                         (int)(system_setting->do_not_disturb),
1198                         (int)(system_setting->visibility_class));
1199
1200         result = _send_sync_noti(body, &reply, "update_noti_sys_setting");
1201
1202         if (reply)
1203                 g_object_unref(reply);
1204
1205         NOTIFICATION_DBG("notification_ipc_update_system_setting done [result: %d]", result);
1206         return result;
1207 }
1208
1209 EXPORT_API GVariant *notification_ipc_make_gvariant_from_noti(notification_h noti)
1210 {
1211         NOTIFICATION_DBG("make gvariant from noti");
1212         int i = 0;
1213         int b_encode_len = 0;
1214         bundle_raw *args = NULL;
1215         bundle_raw *group_args = NULL;
1216         bundle_raw *b_image_path = NULL;
1217         bundle_raw *b_execute_option = NULL;
1218         bundle_raw *b_service_responding = NULL;
1219         bundle_raw *b_service_single_launch = NULL;
1220         bundle_raw *b_service_multi_launch = NULL;
1221         bundle_raw *b_event_handler[NOTIFICATION_EVENT_TYPE_MAX] = {NULL, };
1222         bundle_raw *b_text = NULL;
1223         bundle_raw *b_key = NULL;
1224         bundle_raw *b_format_args = NULL;
1225         GVariant *body = NULL;
1226         GVariant *result_body = NULL;
1227         GVariantBuilder builder;
1228
1229         g_variant_builder_init(&builder, G_VARIANT_TYPE("a{iv}"));
1230         g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_NOTI_TYPE, g_variant_new_int32(noti->type));
1231         g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LAYOUT, g_variant_new_int32(noti->layout));
1232         g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_GROUP_ID, g_variant_new_int32(noti->group_id));
1233         g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_INTERNAL_GROUP_ID, g_variant_new_int32(noti->internal_group_id));
1234         g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PRIV_ID, g_variant_new_int32(noti->priv_id));
1235         g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_CALLER_PKGNAME, g_variant_new_string((const gchar *)noti->caller_pkgname));
1236         g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_DISPLAY_APPLIST, g_variant_new_int32(noti->display_applist));
1237
1238         if (noti->args) {
1239                 bundle_encode(noti->args, (bundle_raw **)&args, NULL);
1240                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_ARGS, g_variant_new_string((const gchar *)args));
1241
1242                 if (args)
1243                         bundle_free_encoded_rawdata(&args);
1244         }
1245
1246         if (noti->group_args) {
1247                 bundle_encode(noti->group_args, (bundle_raw **)&group_args,
1248                               &b_encode_len);
1249                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_GROUP_ARGS, g_variant_new_string((const gchar *)group_args));
1250
1251                 if (group_args)
1252                         bundle_free_encoded_rawdata(&group_args);
1253         }
1254
1255         if (noti->b_execute_option) {
1256                 bundle_encode(noti->b_execute_option,
1257                               (bundle_raw **)&b_execute_option, &b_encode_len);
1258                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_EXECUTE_OPTION, g_variant_new_string((const gchar *)b_execute_option));
1259
1260                 if (b_execute_option)
1261                         bundle_free_encoded_rawdata(&b_execute_option);
1262         }
1263
1264         if (noti->b_service_responding) {
1265                 bundle_encode(noti->b_service_responding,
1266                               (bundle_raw **)&b_service_responding, &b_encode_len);
1267                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_SERVICE_RESPONDING, g_variant_new_string((const gchar *)b_service_responding));
1268
1269                 if (b_service_responding)
1270                         bundle_free_encoded_rawdata(&b_service_responding);
1271         }
1272
1273         if (noti->b_service_single_launch) {
1274                 bundle_encode(noti->b_service_single_launch,
1275                               (bundle_raw **)&b_service_single_launch, &b_encode_len);
1276                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_SERVICE_SINGLE_LAUNCH, g_variant_new_string((const gchar *)b_service_single_launch));
1277
1278                 if (b_service_single_launch)
1279                         bundle_free_encoded_rawdata(&b_service_single_launch);
1280         }
1281
1282         if (noti->b_service_multi_launch) {
1283                 bundle_encode(noti->b_service_multi_launch,
1284                               (bundle_raw **)&b_service_multi_launch, &b_encode_len);
1285                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_SERVICE_MULTI_LAUNCH, g_variant_new_string((const gchar *)b_service_multi_launch));
1286
1287                 if (b_service_multi_launch)
1288                         bundle_free_encoded_rawdata(&b_service_multi_launch);
1289         }
1290
1291         for (i = 0; i < NOTIFICATION_EVENT_TYPE_MAX; i++) {
1292                 if (noti->b_event_handler[i]) {
1293                         bundle_encode(noti->b_event_handler[i],
1294                                         (bundle_raw **)&b_event_handler[i], &b_encode_len);
1295                         g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_BUTTON1_EVENT + i, g_variant_new_string((const gchar *)b_event_handler[i]));
1296
1297                         if (b_event_handler[i])
1298                                 bundle_free_encoded_rawdata(&b_event_handler[i]);
1299                 }
1300         }
1301
1302         if (noti->launch_pkgname)
1303                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LAUNCH_PKGNAME, g_variant_new_string((const gchar *)noti->launch_pkgname));
1304
1305         if (noti->domain != NULL)
1306                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_DOMAIN, g_variant_new_string((const gchar *)noti->domain));
1307
1308         if (noti->dir != NULL)
1309                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_DIR, g_variant_new_string((const gchar *)noti->dir));
1310
1311         if (noti->b_text) {
1312                 bundle_encode(noti->b_text, (bundle_raw **)&b_text, &b_encode_len);
1313                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TEXT, g_variant_new_string((const gchar *)b_text));
1314
1315                 if (b_text)
1316                         bundle_free_encoded_rawdata(&b_text);
1317         }
1318
1319         if (noti->b_key) {
1320                 bundle_encode(noti->b_key, (bundle_raw **)&b_key, &b_encode_len);
1321                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_KEY, g_variant_new_string((const gchar *)b_key));
1322
1323                 if (b_key)
1324                         bundle_free_encoded_rawdata(&b_key);
1325         }
1326
1327         if (noti->b_format_args) {
1328                 bundle_encode(noti->b_format_args,
1329                               (bundle_raw **)&b_format_args, &b_encode_len);
1330                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_FORMAT_ARGS, g_variant_new_string((const gchar *)b_format_args));
1331
1332                 if (b_format_args)
1333                         bundle_free_encoded_rawdata(&b_format_args);
1334         }
1335
1336         if (noti->num_format_args != 0)
1337                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_NUM_FORMAT_ARGS, g_variant_new_int32(noti->num_format_args));
1338
1339         if (noti->b_image_path) {
1340                 bundle_encode(noti->b_image_path,
1341                               (bundle_raw **)&b_image_path, &b_encode_len);
1342                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_IMAGE_PATH, g_variant_new_string((const gchar *)b_image_path));
1343
1344                 if (b_image_path)
1345                         bundle_free_encoded_rawdata(&b_image_path);
1346         }
1347
1348         if (noti->sound_type != NOTIFICATION_SOUND_TYPE_NONE)
1349                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_SOUND_TYPE, g_variant_new_int32(noti->sound_type));
1350
1351         if (noti->sound_path)
1352                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_SOUND_PATH, g_variant_new_string((const gchar *)noti->sound_path));
1353
1354         if (noti->vibration_type != NOTIFICATION_VIBRATION_TYPE_NONE)
1355                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_VIBRATION_TYPE, g_variant_new_int32(noti->vibration_type));
1356
1357         if (noti->vibration_path)
1358                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_VIBRATION_PATH, g_variant_new_string((const gchar *)noti->vibration_path));
1359
1360         if (noti->led_operation != NOTIFICATION_LED_OP_OFF)
1361                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LED_OPERATION, g_variant_new_int32(noti->led_operation));
1362
1363         if (noti->led_argb != 0)
1364                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LED_ARGB, g_variant_new_int32(noti->led_argb));
1365
1366         if (noti->led_on_ms != 0)
1367                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LED_ON_MS, g_variant_new_int32(noti->led_on_ms));
1368
1369         if (noti->led_off_ms != 0)
1370                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LED_OFF_MS, g_variant_new_int32(noti->led_off_ms));
1371
1372         if (noti->time != 0)
1373                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TIME, g_variant_new_int32(noti->time));
1374
1375         if (noti->insert_time != 0)
1376                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_INSERT_TIME, g_variant_new_int32(noti->insert_time));
1377
1378         if (noti->flags_for_property != 0)
1379                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_FLAGS_FOR_PROPERTY, g_variant_new_int32(noti->flags_for_property));
1380
1381         if (noti->progress_size != 0.0)
1382                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PROGRESS_SIZE, g_variant_new_double(noti->progress_size));
1383
1384         if (noti->progress_percentage != 0.0)
1385                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PROGRESS_PERCENTAGE, g_variant_new_double(noti->progress_percentage));
1386
1387         if (noti->app_icon_path != NULL)
1388                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_APP_ICON_PATH, g_variant_new_string((const gchar *)noti->app_icon_path));
1389         if (noti->app_name != NULL)
1390                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_APP_NAME, g_variant_new_string((const gchar *)noti->app_name));
1391         if (noti->temp_title != NULL)
1392                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TEMP_TITLE, g_variant_new_string((const gchar *)noti->temp_title));
1393         if (noti->temp_content != NULL)
1394                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TEMP_CONTENT, g_variant_new_string((const gchar *)noti->temp_content));
1395         if (noti->tag != NULL)
1396                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TAG, g_variant_new_string((const gchar *)noti->tag));
1397
1398         if (noti->ongoing_flag != 0)
1399                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_ONGOING_FLAG, g_variant_new_int32(noti->ongoing_flag));
1400         if (noti->auto_remove != 0)
1401                 g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_AUTO_REMOVE, g_variant_new_int32(noti->auto_remove));
1402
1403         result_body = g_variant_builder_end(&builder);
1404         body = g_variant_new("(v)", result_body);
1405
1406         return body;
1407 }
1408
1409 static gboolean _variant_to_int_dict(GHashTable **dict, GVariant *variant) {
1410
1411         GVariantIter iter;
1412         int key;
1413         int *hash_key;
1414         GVariant *value;
1415
1416         *dict = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, (GDestroyNotify)g_variant_unref);
1417         if (*dict == NULL)
1418                 return FALSE;
1419
1420         g_variant_iter_init(&iter, variant);
1421         while (g_variant_iter_next(&iter, "{iv}", &key, &value)) {
1422                 hash_key = (int *)calloc(sizeof(int), 1);
1423                 if (hash_key == NULL) {
1424                         g_hash_table_remove_all(*dict);
1425                         return FALSE;
1426                 }
1427                 *hash_key = key;
1428                 g_hash_table_insert(*dict, (gpointer)hash_key, value);
1429         }
1430         return TRUE;
1431 }
1432
1433 static gboolean _variant_dict_lookup(GHashTable *dict,
1434                 int key,
1435                 const gchar  *format_string,
1436                 ...)
1437 {
1438         GVariant *value;
1439         va_list ap;
1440
1441         value = g_hash_table_lookup(dict, (gpointer)&key);
1442
1443         if (value == NULL || !g_variant_check_format_string(value, format_string, FALSE))
1444                 return FALSE;
1445
1446         va_start(ap, format_string);
1447         g_variant_get_va(value, format_string, NULL, &ap);
1448         va_end(ap);
1449
1450         return TRUE;
1451 }
1452
1453 /*!
1454  * functions creating notification packet
1455  */
1456 EXPORT_API int notification_ipc_make_noti_from_gvariant(notification_h noti,
1457                 GVariant *variant) {
1458
1459         NOTIFICATION_DBG("make noti from GVariant");
1460         GHashTable *dict;
1461
1462         int i;
1463         char *caller_pkgname = NULL;
1464         char *launch_pkgname = NULL;
1465         bundle_raw *args = NULL;
1466         bundle_raw *group_args = NULL;
1467         bundle_raw *b_execute_option = NULL;
1468         bundle_raw *b_service_responding = NULL;
1469         bundle_raw *b_service_single_launch = NULL;
1470         bundle_raw *b_service_multi_launch = NULL;
1471         bundle_raw *b_event_handler[NOTIFICATION_EVENT_TYPE_MAX] = { NULL, };
1472         char *domain = NULL;
1473         char *dir = NULL;
1474         bundle_raw *b_text = NULL;
1475         bundle_raw *b_key = NULL;
1476         bundle_raw *b_format_args = NULL;
1477         bundle_raw *b_image_path = NULL;
1478         char *sound_path = NULL;
1479         char *vibration_path = NULL;
1480         char *app_icon_path = NULL;
1481         char *app_name = NULL;
1482         char *temp_title = NULL;
1483         char *temp_content = NULL;
1484         char *tag = NULL;
1485
1486         if (noti == NULL) {
1487                 NOTIFICATION_ERR("invalid data noti NULL");
1488                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1489         }
1490
1491         if (variant == NULL) {
1492                 NOTIFICATION_ERR("invalid data variant NULL");
1493                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1494         }
1495
1496         if (!_variant_to_int_dict(&dict, variant))
1497                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1498
1499         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_NOTI_TYPE, "i", &noti->type);
1500         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LAYOUT, "i", &noti->layout);
1501         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_GROUP_ID, "i", &noti->group_id);
1502         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_INTERNAL_GROUP_ID, "i", &noti->internal_group_id);
1503         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PRIV_ID, "i", &noti->priv_id);
1504         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_CALLER_PKGNAME, "&s", &caller_pkgname);
1505         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LAUNCH_PKGNAME, "&s", &launch_pkgname);
1506         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ARGS, "&s", &args);
1507         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_GROUP_ARGS, "&s", &group_args);
1508         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_EXECUTE_OPTION, "&s", &b_execute_option);
1509         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_SERVICE_RESPONDING, "&s", &b_service_responding);
1510         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_SERVICE_SINGLE_LAUNCH, "&s", &b_service_single_launch);
1511         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_SERVICE_MULTI_LAUNCH, "&s", &b_service_multi_launch);
1512         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON1_EVENT, "&s", &noti->b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1]);
1513         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON2_EVENT, "&s", &noti->b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_2]);
1514         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON3_EVENT, "&s", &noti->b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_3]);
1515         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON4_EVENT, "&s", &noti->b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_4]);
1516         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON5_EVENT, "&s", &noti->b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_5]);
1517         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON6_EVENT, "&s", &noti->b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_6]);
1518         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ICON_EVENT, "&s", &noti->b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_ICON]);
1519         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_THUMBNAIL_EVENT, "&s", &noti->b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_THUMBNAIL]);
1520         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_DOMAIN, "&s", &domain);
1521         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_DIR, "&s", &dir);
1522         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TEXT, "&s", &b_text);
1523         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_KEY, "&s", &b_key);
1524         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_FORMAT_ARGS, "&s", &b_format_args);
1525         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_NUM_FORMAT_ARGS, "i", &noti->num_format_args);
1526         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_IMAGE_PATH, "&s", &b_image_path);
1527         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_SOUND_TYPE, "i", &noti->sound_type);
1528         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_SOUND_PATH, "&s", &sound_path);
1529         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_VIBRATION_TYPE, "i", &noti->vibration_type);
1530         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_VIBRATION_PATH, "&s", &vibration_path);
1531         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LED_OPERATION, "i", &noti->led_operation);
1532         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LED_ARGB, "i", &noti->led_argb);
1533         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LED_ON_MS, "i", &noti->led_on_ms);
1534         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LED_OFF_MS, "i", &noti->led_off_ms);
1535         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TIME, "i", &noti->time);
1536         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_INSERT_TIME, "i", &noti->insert_time);
1537         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_FLAGS_FOR_PROPERTY, "i", &noti->flags_for_property);
1538         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_DISPLAY_APPLIST, "i", &noti->display_applist);
1539         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PROGRESS_SIZE, "d", &noti->progress_size);
1540         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PROGRESS_PERCENTAGE, "d", &noti->progress_percentage);
1541         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_APP_ICON_PATH, "&s", &app_icon_path);
1542         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_APP_NAME, "&s", &app_name);
1543         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TEMP_TITLE, "&s", &temp_title);
1544         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TEMP_CONTENT, "&s", &temp_content);
1545         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TAG, "&s", &tag);
1546         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ONGOING_FLAG, "i", &noti->ongoing_flag);
1547         _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_AUTO_REMOVE, "i", &noti->auto_remove);
1548
1549         noti->caller_pkgname = _dup_string(caller_pkgname);
1550         noti->launch_pkgname = _dup_string(launch_pkgname);
1551         noti->args = _create_bundle_from_bundle_raw(args);
1552         noti->group_args = _create_bundle_from_bundle_raw(group_args);
1553         noti->b_execute_option = _create_bundle_from_bundle_raw(b_execute_option);
1554         noti->b_service_responding = _create_bundle_from_bundle_raw(
1555                         b_service_responding);
1556         noti->b_service_single_launch = _create_bundle_from_bundle_raw(
1557                         b_service_single_launch);
1558         noti->b_service_multi_launch = _create_bundle_from_bundle_raw(
1559                         b_service_multi_launch);
1560         for (i = 0; i < NOTIFICATION_EVENT_TYPE_MAX; i++) {
1561                 noti->b_event_handler[i] = _create_bundle_from_bundle_raw(
1562                                 b_event_handler[i]);
1563         }
1564         noti->domain = _dup_string(domain);
1565         noti->dir = _dup_string(dir);
1566         noti->b_text = _create_bundle_from_bundle_raw(b_text);
1567         noti->b_key = _create_bundle_from_bundle_raw(b_key);
1568         noti->b_format_args = _create_bundle_from_bundle_raw(b_format_args);
1569         noti->b_image_path = _create_bundle_from_bundle_raw(b_image_path);
1570         noti->sound_path = _dup_string(sound_path);
1571         noti->vibration_path = _dup_string(vibration_path);
1572         noti->app_icon_path = _dup_string(app_icon_path);
1573         noti->app_name = _dup_string(app_name);
1574         noti->temp_title = _dup_string(temp_title);
1575         noti->temp_content = _dup_string(temp_content);
1576         noti->tag = _dup_string(tag);
1577
1578         g_hash_table_remove_all(dict);
1579
1580         return NOTIFICATION_ERROR_NONE;
1581 }
1582
1583 EXPORT_API GVariant *notification_ipc_make_gvariant_from_system_setting(struct notification_system_setting *noti_setting)
1584 {
1585         GVariant *body = NULL;
1586         body = g_variant_new("(ii)",
1587                         noti_setting->do_not_disturb,
1588                         noti_setting->visibility_class);
1589         return body;
1590 }
1591
1592 EXPORT_API int notification_ipc_make_system_setting_from_gvariant(struct notification_system_setting *noti_setting,
1593                 GVariant *variant)
1594 {
1595         int do_not_disturb;
1596         int visibility_class;
1597
1598         if (noti_setting == NULL) {
1599                 NOTIFICATION_ERR("invalid data");
1600                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1601         }
1602         g_variant_get(variant,
1603                         "(ii)",
1604                         &do_not_disturb,
1605                         &visibility_class);
1606
1607         NOTIFICATION_DBG("system setting  #### %d, %d",
1608                         do_not_disturb, visibility_class);
1609
1610         noti_setting->do_not_disturb = do_not_disturb;
1611         noti_setting->visibility_class = visibility_class;
1612
1613         NOTIFICATION_DBG("system setting2  #### %d, %d",
1614                         noti_setting->do_not_disturb, noti_setting->visibility_class);
1615
1616         return NOTIFICATION_ERROR_NONE;
1617 }
1618
1619 EXPORT_API GVariant *notification_ipc_make_gvariant_from_setting(struct notification_setting *noti_setting)
1620 {
1621         GVariant *body = NULL;
1622
1623         body = g_variant_new("(siii)",
1624                         noti_setting->package_name,
1625                         noti_setting->allow_to_notify,
1626                         noti_setting->do_not_disturb_except,
1627                         noti_setting->visibility_class);
1628
1629         return body;
1630 }
1631
1632 EXPORT_API int notification_ipc_make_setting_from_gvariant(struct notification_setting *noti_setting,
1633                 GVariant *variant)
1634 {
1635         NOTIFICATION_DBG("notification_ipc_make_setting_from_gvariant !!!!");
1636         char *pkgname;
1637         int allow_to_notify;
1638         int do_not_disturb_except;
1639         int visibility_class;
1640
1641         if (noti_setting == NULL || variant == NULL) {
1642                 NOTIFICATION_ERR("invalid data");
1643                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1644         }
1645         g_variant_get(variant,
1646                         "(&siii)",
1647                         &pkgname,
1648                         &allow_to_notify,
1649                         &do_not_disturb_except,
1650                         &visibility_class);
1651
1652         NOTIFICATION_DBG("setting from variant %s !!", pkgname);
1653
1654         noti_setting->package_name = _dup_string(pkgname);
1655         noti_setting->allow_to_notify = allow_to_notify;
1656         noti_setting->do_not_disturb_except = do_not_disturb_except;
1657         noti_setting->visibility_class = visibility_class;
1658
1659         NOTIFICATION_DBG("setting from variant %s, %s",
1660                         noti_setting->package_name, pkgname);
1661
1662         return NOTIFICATION_ERROR_NONE;
1663 }
1664
1665 static int _send_service_register()
1666 {
1667         NOTIFICATION_DBG("service register");
1668         GDBusMessage *reply = NULL;
1669         int result;
1670
1671         result = _send_sync_noti(NULL, &reply, "noti_service_register");
1672
1673         if(reply)
1674                 g_object_unref(reply);
1675
1676         NOTIFICATION_ERR("_send_service_register done = %s, result = %d", _bus_name, result);
1677         return result;
1678 }
1679
1680 static int _ipc_monitor_register(void)
1681 {
1682         NOTIFICATION_ERR("register a service\n");
1683
1684         return  _send_service_register();
1685 }
1686
1687 static void _on_name_appeared(GDBusConnection *connection,
1688                 const gchar     *name,
1689                 const gchar     *name_owner,
1690                 gpointer         user_data)
1691 {
1692         NOTIFICATION_DBG("name appeared : %s", name);
1693         is_master_started = 1;
1694         _ipc_monitor_register();
1695
1696         /* TODO: dbus activation isn't enough ? */
1697         _do_deffered_task();
1698 }
1699
1700 static void _on_name_vanished(GDBusConnection *connection,
1701                 const gchar     *name,
1702                 gpointer         user_data)
1703 {
1704         NOTIFICATION_DBG("name vanished : %s", name);
1705         is_master_started = 0;
1706 }
1707
1708 int notification_ipc_monitor_init(void)
1709 {
1710         int ret;
1711
1712         ret = _dbus_init();
1713         if (ret != NOTIFICATION_ERROR_NONE) {
1714                 NOTIFICATION_ERR("Can't init dbus %d", ret);
1715                 return ret;
1716         }
1717
1718         ret = _dbus_signal_init();
1719         if (ret != NOTIFICATION_ERROR_NONE) {
1720                 NOTIFICATION_ERR("Can't signal_init %d", ret);
1721                 return ret;
1722         }
1723
1724         ret = _ipc_monitor_register();
1725         if (ret != NOTIFICATION_ERROR_NONE) {
1726                 NOTIFICATION_ERR("Can't init ipc_monitor_register %d", ret);
1727                 return ret;
1728         }
1729
1730         if (provider_monitor_id == 0) {
1731                 provider_monitor_id = g_bus_watch_name_on_connection(
1732                                 _gdbus_conn,
1733                                 PROVIDER_BUS_NAME,
1734                                 G_BUS_NAME_WATCHER_FLAGS_NONE,
1735                                 _on_name_appeared,
1736                                 _on_name_vanished,
1737                                 NULL,
1738                                 NULL);
1739
1740                 if (provider_monitor_id == 0) {
1741                         g_dbus_connection_signal_unsubscribe(_gdbus_conn, monitor_id);
1742                         monitor_id = 0;
1743                         NOTIFICATION_ERR("watch on name fail");
1744                         return NOTIFICATION_ERROR_IO_ERROR;
1745                 }
1746         }
1747
1748         return NOTIFICATION_ERROR_NONE;
1749 }
1750
1751 static int _ipc_monitor_deregister(void)
1752 {
1753         if (provider_monitor_id) {
1754                 g_bus_unwatch_name(provider_monitor_id);
1755                 provider_monitor_id = 0;
1756         }
1757
1758         if (monitor_id) {
1759                 g_dbus_connection_signal_unsubscribe(_gdbus_conn, monitor_id);
1760                 monitor_id = 0;
1761         }
1762
1763         return NOTIFICATION_ERROR_NONE;
1764 }
1765
1766 int notification_ipc_monitor_fini(void)
1767 {
1768         return  _ipc_monitor_deregister();
1769 }