Use pkgmgrinfo_appinfo_foreach_appcontrol
[platform/core/appfw/event-system.git] / src / esd_main.c
1 #include <stdio.h>
2 #include <glib.h>
3 #include <aul.h>
4 #include <unistd.h>
5 #include <ctype.h>
6 #include <dlog.h>
7 #include <Ecore.h>
8 #include <gio/gio.h>
9 #include <assert.h>
10 #include <package-manager.h>
11 #include <pkgmgr-info.h>
12 #include <appsvc/appsvc.h>
13 #include <eventsystem.h>
14 #include <bundle.h>
15
16 #undef LOG_TAG
17 #define LOG_TAG "ESD"
18
19 #define _E(fmt, arg...) LOGE(fmt, ##arg)
20 #define _D(fmt, arg...) LOGD(fmt, ##arg)
21 #define _W(fmt, arg...) LOGW(fmt, ##arg)
22 #define _I(fmt, arg...) LOGI(fmt, ##arg)
23
24 #define retvm_if(expr, val, fmt, arg...) do { \
25         if (expr) { \
26                 _E(fmt, ##arg); \
27                 _E("(%s) -> %s() return", #expr, __func__); \
28                 return val; \
29         } \
30 } while (0)
31
32 #define retv_if(expr, val) do { \
33         if (expr) { \
34                 _E("(%s) -> %s() return", #expr, __func__); \
35                 return val; \
36         } \
37 } while (0)
38
39 static GHashTable *event_launch_table; /* table of events for launch_on_event*/
40
41 #ifdef APPFW_EVENT_SYSTEM_EARLIER_FEATURE
42 const char *earlier_event_list[] = {
43         SYS_EVENT_ESD_STATUS,
44         SYS_EVENT_BATTERY_CHARGER_STATUS,
45         SYS_EVENT_USB_STATUS,
46         SYS_EVENT_LOW_MEMORY,
47         SYS_EVENT_BOOT_COMPLETED,
48         SYS_EVENT_SYSTEM_SHUTDOWN
49 };
50
51 static GHashTable *earlier_event_table; /* table of events for earlier_data */
52
53 typedef struct __earlier_table_item {
54         char *event_name;
55         guint reg_id;
56         bundle *earlier_data; /* event-data from earlier occurrence */
57 } earlier_item;
58 #endif
59
60 typedef struct __eventlaunch_item_param {
61         char *app_id;
62 } eventlaunch_item_param_s;
63
64 typedef struct esd_list_item {
65         char *pkg_id;
66         char *app_id;
67 } esd_list_item_s;
68
69 typedef struct  __event_launch_table_item {
70         char *event_name;
71         char *package_name; /* just for passing pointer to app-list removal func */
72         GList *app_list_evtlaunch; /* app-list for on-event-launch */
73         guint reg_id;
74 } event_launch_item;
75
76 enum __pkg_event_type {
77         UNKNOWN = 0,
78         INSTALL,
79         UNINSTALL,
80         UPDATE,
81 };
82
83 typedef struct __pkgmgr_event {
84         int type;
85         char *pkgid;
86 } esd_pkgmgr_event;
87
88 typedef struct __esd_event_param {
89         char *event_name;
90         bundle *event_data;
91         void *user_data;
92 } esd_event_param;
93
94 typedef struct esd_info {
95         pkgmgr_client *client;
96 } esd_info_s;
97 static esd_info_s s_info;
98
99
100 static int __esd_add_appinfo_handler(const pkgmgrinfo_appinfo_h handle, void *data);
101 static void __esd_event_handler(char *event_name, bundle *data, void *user_data);
102
103 static int __get_sender_pid(GDBusConnection *conn, const char *sender_name)
104 {
105         GDBusMessage *msg = NULL;
106         GDBusMessage *reply = NULL;
107         GError *err = NULL;
108         GVariant *body;
109         int pid = 0;
110
111         msg = g_dbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
112                 "org.freedesktop.DBus", "GetConnectionUnixProcessID");
113         if (!msg) {
114                 _D("Can't allocate new method call");
115                 goto out;
116         }
117
118         g_dbus_message_set_body(msg, g_variant_new ("(s)", sender_name));
119         reply = g_dbus_connection_send_message_with_reply_sync(conn, msg,
120                 G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
121
122         if (!reply) {
123                 if (err != NULL) {
124                         _E("Failed to get pid [%s]", err->message);
125                         g_error_free(err);
126                 }
127                 goto out;
128         }
129
130         body = g_dbus_message_get_body(reply);
131         g_variant_get(body, "(u)", &pid);
132
133 out:
134         if (msg)
135                 g_object_unref(msg);
136         if (reply)
137                 g_object_unref(reply);
138
139   return pid;
140 }
141
142 void __esd_free_app_list(gpointer data)
143 {
144         char *n = (char *)data;
145
146         FREE_AND_NULL(n);
147 }
148
149 static void esd_print_appid_with_eventid(gpointer data, gpointer user_data)
150 {
151         esd_list_item_s *item = (esd_list_item_s *)data;
152         char *event_name = (char *)user_data;
153
154         _D("event_name(%s)-app_id(%s)-pkg_id(%s)", event_name, item->app_id, item->pkg_id);
155 }
156
157 static void esd_print_interested_event(gpointer data, gpointer user_data)
158 {
159         event_launch_item *el_item = (event_launch_item *)data;
160         char *event_name = (char *)el_item->event_name;
161         _D("event_name = (%s)", event_name);
162         g_list_foreach(el_item->app_list_evtlaunch, esd_print_appid_with_eventid, event_name);
163 }
164
165 static void esd_launch_table_print_items(void)
166 {
167         GHashTableIter iter;
168         gpointer key, value;
169
170         g_hash_table_iter_init(&iter, event_launch_table);
171
172         while (g_hash_table_iter_next(&iter, &key, &value)) {
173                 esd_print_interested_event(value, NULL);
174         }
175 }
176
177 static int esd_find_compare_by_list_item(gconstpointer data, gconstpointer user_data)
178 {
179         esd_list_item_s *item_1 = (esd_list_item_s *)user_data;
180         esd_list_item_s *item_2 = (esd_list_item_s *)data;
181
182         return strcmp(item_1->app_id, item_2->app_id) |
183                 strcmp(item_1->pkg_id, item_2->pkg_id);
184 }
185
186 static int __esd_get_pkgid_by_appid(const char *app_id, char **pkg_id)
187 {
188         pkgmgrinfo_appinfo_h handle = NULL;
189         char *temp_val = NULL;
190         int ret = 0;
191
192         *pkg_id = NULL;
193
194         ret = pkgmgrinfo_appinfo_get_usr_appinfo(app_id, getuid(), &handle);
195         if (ret < 0) {
196                 _E("failed to get appinfo");
197                 ret = ES_R_ERROR;
198                 goto out;
199         }
200
201         ret = pkgmgrinfo_appinfo_get_pkgname(handle, &temp_val);
202         if (ret == PMINFO_R_OK && temp_val) {
203                 *pkg_id = strdup(temp_val);
204                 _D("pkg_id(%s)", *pkg_id);
205         } else {
206                 _E("failed to get pkgname");
207                 ret = pkgmgrinfo_appinfo_destroy_appinfo(handle);
208                 if (ret != PMINFO_R_OK) {
209                         _E("failed to destroy appinfo");
210                 }
211                 ret = ES_R_ERROR;
212                 goto out;
213         }
214         ret = pkgmgrinfo_appinfo_destroy_appinfo(handle);
215         if (ret != PMINFO_R_OK) {
216                 _E("failed to destroy appinfo");
217                 free(*pkg_id);
218                 ret = ES_R_ERROR;
219                 goto out;
220         }
221
222         ret = ES_R_OK;
223
224 out:
225         return ret;
226 }
227
228 static int __esd_add_list_item(event_launch_item *el_item,
229                 const char *app_id, const char *pkg_id)
230 {
231         char *_pkgid = NULL;
232         esd_list_item_s *item_of_list = NULL;
233
234         if (pkg_id == NULL) {
235                 if (__esd_get_pkgid_by_appid(app_id, &_pkgid) < 0) {
236                         return ES_R_ERROR;
237                 }
238         } else {
239                 _pkgid = (char *)pkg_id;
240         }
241
242         item_of_list = calloc(1, sizeof(esd_list_item_s));
243         if (item_of_list == NULL) {
244                 _E("out_of_memory");
245                 free(_pkgid);
246                 return ES_R_ENOMEM;
247         }
248         item_of_list->app_id = (char *)app_id;
249         item_of_list->pkg_id = _pkgid;
250         el_item->app_list_evtlaunch =
251                 g_list_append(el_item->app_list_evtlaunch, item_of_list);
252
253         return ES_R_OK;
254 }
255
256 static int __esd_add_launch_item(const char *event_name, const char *appid)
257 {
258         GList *app_list = NULL;
259         guint subscription_id = 0;
260         char *app_id = NULL;
261         char *pkg_id = NULL;
262         esd_list_item_s *item_of_list = NULL;
263
264         event_launch_item *el_item =
265                 (event_launch_item *)g_hash_table_lookup(event_launch_table, event_name);
266
267         if (el_item) {
268                 if (__esd_get_pkgid_by_appid(appid, &pkg_id) < 0) {
269                         return ES_R_ERROR;
270                 }
271                 item_of_list = calloc(1, sizeof(esd_list_item_s));
272                 if (item_of_list == NULL) {
273                         _E("memory alloc failed");
274                         free(pkg_id);
275                         return ES_R_ENOMEM;
276                 }
277                 item_of_list->app_id = (char *)appid;
278                 item_of_list->pkg_id = pkg_id;
279
280                 app_list = g_list_find_custom(el_item->app_list_evtlaunch,
281                                 item_of_list, (GCompareFunc)esd_find_compare_by_list_item);
282                 free(item_of_list);
283                 if (app_list == NULL) {
284                         _D("add new item (list item only)");
285                         app_id = strdup((char *)appid);
286                         if (!app_id) {
287                                 _E("out_of_memory");
288                                 free(pkg_id);
289                                 return ES_R_ENOMEM;
290                         }
291                         if (__esd_add_list_item(el_item, app_id, pkg_id) < 0) {
292                                 _E("failed to add list item");
293                                 free(app_id);
294                                 free(pkg_id);
295                                 return ES_R_ERROR;
296                         }
297                 }
298         } else {
299                 _D("add new item (all)");
300                 event_launch_item *eli = calloc(1, sizeof(event_launch_item));
301                 if (!eli) {
302                         _E("memory alloc failed");
303                         return ES_R_ENOMEM;
304                 }
305
306                 eli->event_name = strdup(event_name);
307                 if (!eli->event_name) {
308                         _E("out_of_memory");
309                         FREE_AND_NULL(eli);
310                         return ES_R_ENOMEM;
311                 }
312
313                 app_id = strdup((char *)appid);
314                 if (!app_id) {
315                         _E("out_of_memory");
316                         FREE_AND_NULL(eli->event_name);
317                         FREE_AND_NULL(eli);
318                         return ES_R_ENOMEM;
319                 }
320                 if (__esd_add_list_item(eli, app_id, NULL) < 0) {
321                         _E("failed to add list item");
322                         free(app_id);
323                         FREE_AND_NULL(eli->event_name);
324                         FREE_AND_NULL(eli);
325                         return ES_R_ERROR;
326                 }
327
328                 g_hash_table_insert(event_launch_table, eli->event_name, eli);
329
330                 eventsystem_register_event(eli->event_name, &subscription_id,
331                                         (eventsystem_handler)__esd_event_handler, NULL);
332                 if (subscription_id == 0) {
333                         _E("signal subscription error, event_name(%s), app_id(%s)",
334                                 eli->event_name, app_id);
335                         return ES_R_ERROR;
336                 } else {
337                         eli->reg_id = subscription_id;
338                 }
339         }
340
341         return ES_R_OK;
342 }
343
344 static void __esd_remove_app_list(gpointer data, gpointer user_data)
345 {
346         esd_list_item_s *item = (esd_list_item_s *)data;
347         event_launch_item *eli = (event_launch_item *)user_data;
348
349         if (!strcmp(eli->package_name, item->pkg_id)) {
350                 _D("pkg_id(%s), app_id(%s)", eli->package_name, item->app_id);
351                 eli->app_list_evtlaunch =
352                         g_list_remove_all(eli->app_list_evtlaunch, data);
353         }
354 }
355
356 static int esd_remove_launch_item(gpointer data, const char *pkg_id)
357 {
358         event_launch_item *eli = (event_launch_item *)data;
359         GList *first_list = NULL;
360
361         eli->package_name = (char *)pkg_id;
362         g_list_foreach(eli->app_list_evtlaunch, __esd_remove_app_list, eli);
363
364         first_list = g_list_first(eli->app_list_evtlaunch);
365         if (first_list == NULL) {
366                 if (eli->reg_id) {
367                         eventsystem_unregister_event(eli->reg_id);
368                 }
369                 return ES_R_REMOVE;
370         }
371
372         return ES_R_OK;
373 }
374
375 static int esd_launch_table_remove_items(const char *pkg_id)
376 {
377         GHashTableIter iter;
378         gpointer key, value;
379
380         g_hash_table_iter_init(&iter, event_launch_table);
381
382         while (g_hash_table_iter_next(&iter, &key, &value)) {
383                 if (esd_remove_launch_item(value, pkg_id) == ES_R_REMOVE) {
384                         _D("remove item itself");
385                         g_hash_table_iter_remove(&iter);
386                 }
387         }
388
389         return ES_R_OK;
390 }
391
392 static void esd_event_launch_with_appid(gpointer data, gpointer user_data)
393 {
394         esd_list_item_s *item = (esd_list_item_s *)data;
395         char *app_id = item->app_id;
396         esd_event_param *eep = (esd_event_param *)user_data;
397         static unsigned int req_id;
398         int pid;
399
400         _D("launch_on_event: app_id(%s), event_name(%s)", app_id, eep->event_name);
401
402         if (!aul_app_is_running(app_id)) {
403                 char event_uri[1024] = {0, };
404                 snprintf(event_uri, 1024, "event://%s", eep->event_name);
405                 bundle *b = bundle_dup(eep->event_data);
406                 appsvc_set_operation(b, APPSVC_OPERATION_LAUNCH_ON_EVENT);
407                 appsvc_set_uri(b, event_uri);
408                 appsvc_set_appid(b, app_id);
409
410                 pid = appsvc_usr_run_service(b, req_id++, NULL, eep->user_data, getuid());
411                 _D("pid(%d)", pid);
412
413                 bundle_free(b);
414         } else {
415                 _D("already is running");
416         }
417 }
418
419 static void esd_check_event_launch_with_eventid(gpointer data, gpointer user_data)
420 {
421         event_launch_item *el_item = (event_launch_item *)data;
422         esd_event_param *eep = (esd_event_param *)user_data;
423
424         if (strcmp(eep->event_name, (char *)el_item->event_name) == 0) {
425                 g_list_foreach(el_item->app_list_evtlaunch,
426                         esd_event_launch_with_appid, user_data);
427         }
428 }
429
430 static void __esd_event_handler(char *event_name, bundle *data, void *user_data)
431 {
432         _D("event_name(%s)", event_name);
433
434         event_launch_item *el_item =
435                 (event_launch_item *)g_hash_table_lookup(event_launch_table, event_name);
436
437         if (el_item == NULL) {
438                 return;
439         }
440
441         if (el_item->app_list_evtlaunch != NULL) {
442                 esd_event_param *eep = calloc(1, sizeof(esd_event_param));
443                 if (!eep) {
444                         _E("memory alloc failed");
445                         return;
446                 }
447                 eep->event_name = event_name;
448                 eep->event_data = data;
449                 eep->user_data = (void *)user_data;
450                 esd_check_event_launch_with_eventid(el_item, eep);
451                 free(eep);
452         }
453 }
454
455 #ifdef APPFW_EVENT_SYSTEM_EARLIER_FEATURE
456 static void __esd_earlier_event_handler(char *event_name, bundle *data, void *user_data)
457 {
458         _D("event_name(%s)", event_name);
459
460         earlier_item *item =
461                 (earlier_item *)g_hash_table_lookup(earlier_event_table, event_name);
462
463         /* update earlier value */
464         if (item->earlier_data != NULL) {
465                 bundle_free(item->earlier_data);
466         }
467         item->earlier_data = bundle_dup(data);
468 }
469 #endif
470
471 static GDBusNodeInfo *introspection_data;
472 static const gchar introspection_xml[] =
473 "<node>"
474 "       <interface name='tizen.system.event.app2esd'>"
475 "               <method name='CheckUserCertValidation'>"
476 "                       <arg type='i' name='frompid' direction='in'/>"
477 "                       <arg type='i' name='ret' direction='out'/>"
478 "               </method>"
479 "               <method name='CheckUserSendValidation'>"
480 "                       <arg type='s' name='eventname' direction='in'/>"
481 "                       <arg type='i' name='ret' direction='out'/>"
482 "               </method>"
483 "               <method name='RequestEventLaunch'>"
484 "                       <arg type='s' name='eventname' direction='in'/>"
485 "                       <arg type='s' name='eventdata' direction='in'/>"
486 "                       <arg type='i' name='datalen' direction='in'/>"
487 "                       <arg type='i' name='ret' direction='out'/>"
488 "               </method>"
489 "               <method name='RequestSendingEvent'>"
490 "                       <arg type='s' name='eventname' direction='in'/>"
491 "                       <arg type='s' name='eventdata' direction='in'/>"
492 "                       <arg type='i' name='datalen' direction='in'/>"
493 "                       <arg type='i' name='ret' direction='out'/>"
494 "               </method>"
495 #ifdef APPFW_EVENT_SYSTEM_EARLIER_FEATURE
496 "               <method name='GetEarlierData'>"
497 "                       <arg type='s' name='appid' direction='in'/>"
498 "                       <arg type='i' name='ret' direction='out'/>"
499 "                       <arg type='i' name='len' direction='out'/>"
500 "                       <arg type='s' name='earlier_data' direction='out'/>"
501 "               </method>"
502 #endif
503 "       </interface>"
504 "</node>";
505
506 static void handle_method_call(GDBusConnection *connection,
507                 const gchar *sender, const gchar *object_path,
508                 const gchar *interface_name, const gchar *method_name,
509                 GVariant *parameters, GDBusMethodInvocation *invocation,
510                 gpointer user_data)
511 {
512         GVariant *param = NULL;
513         int result = 0;
514
515         if (g_strcmp0(method_name, "CheckUserCertValidation") == 0) {
516                 char app_id[256] = {0, };
517                 char from_appid[256] = {0, };
518                 int from_pid = 0;
519                 int sender_pid = 0;
520                 int ret = 0;
521
522                 g_variant_get(parameters, "(i)", &from_pid);
523
524                 _D("from_pid(%d)", from_pid);
525
526                 if (from_pid > 0) {
527                         ret = aul_app_get_appid_bypid(from_pid, from_appid, sizeof(from_appid));
528                         if (ret != AUL_R_OK) {
529                                 _E("failed to get appid by from_pid");
530                                 result = ES_R_ERROR;
531                                 goto out_1;
532                         }
533                 }
534
535                 sender_pid = __get_sender_pid(connection, sender);
536
537                 if (sender_pid > 0) {
538                         ret = aul_app_get_appid_bypid(sender_pid, app_id, sizeof(app_id));
539                         if (ret != AUL_R_OK) {
540                                 _E("failed to get appid by sender_pid");
541                                 result = ES_R_ERROR;
542                                 goto out_1;
543                         }
544                 } else {
545                         _E("failed to get sender_pid");
546                         goto out_1;
547                 }
548
549                 pkgmgrinfo_cert_compare_result_type_e res;
550                 ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(app_id, from_appid,
551                                 getuid(), &res);
552                 if (ret < 0) {
553                         _E("CheckCertificate() Failed");
554                         result = ES_R_ERROR;
555                         goto out_1;
556                 }
557
558                 if (res != PMINFO_CERT_COMPARE_MATCH) {
559                         _E("CheckCertificate() Failed : ERROR_CERTIFICATE_NOT_MATCH");
560                         result = ES_R_EINVAL;
561                         goto out_1;
562                 }
563
564                 result = 1;
565                 param = g_variant_new("(i)", result);
566 out_1:
567                 _D("app_id(%s), from_appid(%s), result(%d)", app_id, from_appid, result);
568                 g_dbus_method_invocation_return_value(invocation, param);
569         } else if (g_strcmp0(method_name, "CheckUserSendValidation") == 0) {
570                 char *event_name = NULL;
571                 char app_id[256] = {0, };
572                 char valid_name[1024];
573                 char *user_defined_name = NULL;
574                 int sender_pid = 0;
575                 int ret = 0;
576                 int len = 0;
577
578                 g_variant_get(parameters, "(s)", &event_name);
579
580                 _D("event_name(%s)", event_name);
581
582                 sender_pid = __get_sender_pid(connection, sender);
583
584                 if (sender_pid > 0) {
585                         ret = aul_app_get_appid_bypid(sender_pid, app_id, sizeof(app_id));
586                         if (ret != AUL_R_OK) {
587                                 _E("failed to get appid by sender_pid");
588                                 result = ES_R_ERROR;
589                                 goto out_2;
590                         }
591                 } else {
592                         _E("failed to get sender_pid");
593                         goto out_2;
594                 }
595
596                 snprintf(valid_name, 1024, "%s%s.", USER_EVENT_NAME_PREFIX, app_id);
597                 len = strlen(valid_name);
598
599                 _D("valid_name(%s)", valid_name);
600
601                 if (strncmp(event_name, valid_name, len) != 0) {
602                         _E("appid misamatch");
603                         result = ES_R_EINVAL;
604                         goto out_2;
605                 } else {
606                         user_defined_name = strdup(&event_name[len]);
607                         len = strlen(user_defined_name);
608                         if (len < 1 || len > 127) {
609                                 _E("Invalid Length of user-defined name");
610                                 result = ES_R_EINVAL;
611                                 goto out_2;
612                         }
613                         free(user_defined_name);
614                 }
615
616                 result = 1;
617                 param = g_variant_new("(i)", result);
618 out_2:
619                 _D("event_name(%s), result(%d)", event_name, result);
620                 g_dbus_method_invocation_return_value(invocation, param);
621         } else if (g_strcmp0(method_name, "RequestEventLaunch") == 0) {
622                 char *event_name = NULL;
623                 bundle_raw *raw = NULL;
624                 bundle *b = NULL;
625                 int len = 0;
626
627                 g_variant_get(parameters, "(ssi)", &event_name, &raw, &len);
628
629                 b = bundle_decode(raw, len);
630                 __esd_event_handler(event_name, b, NULL);
631                 bundle_free(b);
632
633                 result = 1;
634                 param = g_variant_new("(i)", result);
635
636                 _D("event_name(%s), result(%d)", event_name, result);
637                 g_dbus_method_invocation_return_value(invocation, param);
638         } else if (g_strcmp0(method_name, "RequestSendingEvent") == 0) {
639                 char *event_name = NULL;
640                 bundle_raw *raw = NULL;
641                 bundle *b = NULL;
642                 int len = 0;
643
644                 g_variant_get(parameters, "(ssi)", &event_name, &raw, &len);
645
646                 b = bundle_decode(raw, len);
647                 eventsystem_send_system_event(event_name, b);
648                 bundle_free(b);
649
650                 result = 1;
651                 param = g_variant_new("(i)", result);
652
653                 _D("event_name(%s), result(%d)", event_name, result);
654                 g_dbus_method_invocation_return_value(invocation, param);
655 #ifdef APPFW_EVENT_SYSTEM_EARLIER_FEATURE
656         } else if (g_strcmp0(method_name, "GetEarlierData") == 0) {
657                 char *event_name = NULL;
658                 bundle *b = NULL;
659                 bundle_raw *raw = NULL;
660                 int len = 0;
661
662                 g_variant_get(parameters, "(s)", &event_name);
663
664                 if (event_name && strlen(event_name) > 0) {
665                         _D("event_name(%s)", event_name);
666                         result = ES_R_OK;
667                 } else {
668                         _E("invalid appid(%s)", event_name);
669                         result = ES_R_ERROR;
670                 }
671
672                 earlier_item *item =
673                         (earlier_item *)g_hash_table_lookup(earlier_event_table, event_name);
674
675                 if (item != NULL) {
676                         if (item->earlier_data) {
677                                 b = bundle_dup(item->earlier_data);
678                                 bundle_add_str(b, "is_earlier_data", "true");
679                                 bundle_encode(b, &raw, &len);
680                                 bundle_free(b);
681                         }
682                 }
683
684                 param = g_variant_new("(iis)", result, len, raw);
685
686                 _D("result(%d), len(%d)", result, len);
687                 g_dbus_method_invocation_return_value(invocation, param);
688
689                 bundle_free_encoded_rawdata(&raw);
690 #endif
691         }
692 }
693
694 static const GDBusInterfaceVTable interface_vtable = {
695         handle_method_call,
696         NULL,
697         NULL
698 };
699
700 static void on_bus_acquired(GDBusConnection *connection,
701                 const gchar *name, gpointer user_data)
702 {
703         _D("on_bus_acquired(%s)", name);
704
705         guint reg_id = 0;
706         GError *error = NULL;
707
708         reg_id = g_dbus_connection_register_object(connection,
709                 ESD_OBJECT_PATH,
710                 introspection_data->interfaces[0],
711                 &interface_vtable,
712                 NULL, NULL, &error);
713         if (reg_id == 0) {
714                 _E("g_dbus_connection_register_object error(%s)", error->message);
715                 g_error_free (error);
716         }
717 }
718
719 static void on_name_acquired(GDBusConnection *connection,
720                 const gchar *name, gpointer user_data)
721 {
722         _D("on_name_acquired(%s)", name);
723
724         bundle *b = bundle_create();
725         bundle_add_str(b, EVT_KEY_ESD_STATUS, EVT_VAL_ESD_STARTED);
726         eventsystem_send_system_event(SYS_EVENT_ESD_STATUS, b);
727         bundle_free(b);
728 }
729
730 static void on_name_lost(GDBusConnection *connection,
731                 const gchar *name, gpointer user_data)
732 {
733         _D("on_name_lost(%s)", name);
734 }
735
736 static int __esd_before_loop(void)
737 {
738         int ret = 0;
739
740 #ifdef APPFW_EVENT_SYSTEM_EARLIER_FEATURE
741         guint subscription_id = 0;
742         int i, size;
743
744         earlier_event_table = g_hash_table_new(g_str_hash, g_str_equal);
745
746         _I("register events for earlier_data");
747         size = sizeof(earlier_event_list)/sizeof(*earlier_event_list);
748         for (i = 0; i < size; i++) {
749                 char *event_name = NULL;
750                 event_name = (char *)earlier_event_list[i];
751                 _I("event_name(%s)", event_name);
752
753                 earlier_item *item = calloc(1, sizeof(earlier_item));
754                 item->event_name = strdup(event_name);
755                 if (item->event_name == NULL) {
756                         _E("out of memory");
757                         return ES_R_ERROR;
758                 }
759                 g_hash_table_insert(earlier_event_table, event_name, item);
760
761                 eventsystem_register_event(item->event_name, &subscription_id,
762                                         (eventsystem_handler)__esd_earlier_event_handler, NULL);
763                 if (subscription_id == 0) {
764                         _E("signal subscription error, event_name(%s)", item->event_name);
765                         return ES_R_ERROR;
766                 } else {
767                         item->reg_id = subscription_id;
768                 }
769         }
770 #endif
771
772         event_launch_table = g_hash_table_new(g_str_hash, g_str_equal);
773
774         _I("get event launch list");
775         ret = pkgmgrinfo_appinfo_get_usr_installed_list(__esd_add_appinfo_handler, getuid(), NULL);
776         if (ret < 0) {
777                 _E("pkgmgrinfo_appinfo_get_usr_installed_list error");
778                 return ES_R_ERROR;
779         }
780         esd_launch_table_print_items();
781         /* gdbus setup for method call */
782         GError *error = NULL;
783         guint owner_id = 0;
784         introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, &error);
785         if (!introspection_data) {
786                 _E("g_dbus_node_info_new_for_xml error(%s)", error->message);
787                 g_error_free (error);
788                 return ES_R_ERROR;
789         }
790
791         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
792                 ESD_BUS_NAME,
793                 G_BUS_NAME_OWNER_FLAGS_NONE,
794                 on_bus_acquired,
795                 on_name_acquired,
796                 on_name_lost,
797                 NULL, NULL);
798         if (!owner_id) {
799                 _E("g_bus_own_name error");
800                 g_dbus_node_info_unref(introspection_data);
801                 return ES_R_ERROR;
802         }
803
804         return ES_R_OK;
805 }
806
807 static void esd_pkgmgr_event_free(esd_pkgmgr_event *pkg_event)
808 {
809         pkg_event->type = UNKNOWN;
810         if (pkg_event->pkgid) {
811                 free(pkg_event->pkgid);
812                 pkg_event->pkgid = NULL;
813         }
814 }
815
816 #define OPERATION_LAUNCH_ON_EVENT "http://tizen.org/appcontrol/operation/launch_on_event"
817 static int __esd_appcontrol_cb(const char *operation, const char *uri, const char *mime, void *data)
818 {
819         char *appid = (char *)data;
820
821         if (!strcmp(operation, OPERATION_LAUNCH_ON_EVENT)) {
822                 if (__esd_add_launch_item(uri, appid)) {
823                         _E("failed to add item for %s", appid);
824                 }
825         }
826
827         return 0;
828 }
829
830 static int __esd_add_appinfo_handler(const pkgmgrinfo_appinfo_h handle, void *data)
831 {
832         char *appid = NULL;
833         pkgmgrinfo_app_component component_type;
834         int ret = 0;
835
836         ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
837         if (ret < 0) {
838                 _E("fail to get appinfo");
839                 return ES_R_ERROR;
840         }
841
842         _D("appid(%s)", appid);
843
844         ret = pkgmgrinfo_appinfo_get_component(handle, &component_type);
845         if (ret != PMINFO_R_OK) {
846                 _E("failed to get component type");
847                 return ES_R_ERROR;
848         }
849
850         if (component_type != PMINFO_SVC_APP) {
851                 _E("not service app");
852                 return ES_R_OK;
853         }
854
855         ret = pkgmgrinfo_appinfo_foreach_appcontrol(handle, __esd_appcontrol_cb, appid);
856         if (ret < 0) {
857                 _E("failed to get appcontrol info");
858                 return ES_R_ERROR;
859         }
860
861         return ES_R_OK;
862 }
863
864 static int esd_pkgmgr_event_callback(uid_t target_uid, int req_id, const char *pkg_type,
865                 const char *pkgid, const char *key, const char *val,
866                 const void *pmsg, void *data)
867 {
868         esd_pkgmgr_event *pkg_event = (esd_pkgmgr_event *)data;
869         pkgmgrinfo_pkginfo_h handle = NULL;
870         int ret = 0;
871
872         _D("req_id(%d), pkg_type(%s), pkgid(%s), key(%s), val(%s)",
873                 req_id, pkg_type, pkgid, key, val);
874
875         if (strncmp(key, "start", strlen(key)) == 0) {
876                 if (strcmp(val, "install") == 0) {
877                         _D("install start");
878                         pkg_event->type = INSTALL;
879                 } else if (strcmp(val, "uninstall") == 0) {
880                         _D("unistall start");
881                         pkg_event->type = UNINSTALL;
882                 } else if (strcmp(val, "update") == 0) {
883                         _D("update start");
884                         pkg_event->type = UPDATE;
885                 } else {
886                         _D("val(%s) start", val);
887                         esd_pkgmgr_event_free(pkg_event);
888                 }
889         } else if (strcmp(key, "end") == 0 && strcmp(val, "ok") == 0) {
890                 if (pkg_event->type == INSTALL || pkg_event->type == UPDATE) {
891                         _D("install end (ok)");
892                         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, getuid(), &handle);
893                         if (ret < 0) {
894                                 _E("failed to get pkginfo");
895                                 esd_pkgmgr_event_free(pkg_event);
896                                 return 0;
897                         }
898                         ret = pkgmgrinfo_appinfo_get_list(handle,
899                                 PMINFO_SVC_APP, __esd_add_appinfo_handler, NULL);
900                         if (ret < 0) {
901                                 _E("failed to get appinfo");
902                                 esd_pkgmgr_event_free(pkg_event);
903                                 return 0;
904                         }
905                         ret = pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
906                         if (ret < 0) {
907                                 _E("failed to destroy pkginfo");
908                                 esd_pkgmgr_event_free(pkg_event);
909                                 return 0;
910                         }
911                 } else if (pkg_event->type == UNINSTALL) {
912                         _D("uninstall end (ok)");
913                         esd_launch_table_remove_items(pkgid);
914                         esd_launch_table_print_items();
915                 }
916                 esd_pkgmgr_event_free(pkg_event);
917         } else if (strcmp(key, "end") == 0 && strcmp(val, "fail") == 0) {
918                 _E("pkg_event(%d) falied", pkg_event->type);
919                 esd_pkgmgr_event_free(pkg_event);
920         } else {
921                 if (strcmp(key, "install_percent") != 0) {
922                         esd_pkgmgr_event_free(pkg_event);
923                 }
924         }
925
926         return 0;
927 }
928
929 static int __esd_init()
930 {
931         int req_id = 0;
932         int ret = 0;
933
934         g_type_init();
935         ecore_init();
936
937         pkgmgr_client *client = pkgmgr_client_new(PC_LISTENING);
938         if (client == NULL) {
939                 _E("set pkgmgr client failed");
940                 return ES_R_ERROR;
941         }
942
943         esd_pkgmgr_event *pkg_event = calloc(1, sizeof(esd_pkgmgr_event));
944         if (pkg_event == NULL) {
945                 _E("memory alloc failed");
946                 ret = pkgmgr_client_free(client);
947                 if (ret != PKGMGR_R_OK) {
948                         _E("pkgmgr_client_free failed(%d)", ret);
949                 }
950                 return ES_R_ENOMEM;
951         }
952
953         req_id = pkgmgr_client_listen_status(client, esd_pkgmgr_event_callback, pkg_event);
954         if (req_id < 0) {
955                 _E("pkgmgr client listen failed");
956                 ret = pkgmgr_client_free(client);
957                 if (ret != PKGMGR_R_OK) {
958                         _E("pkgmgr_client_free failed(%d)", ret);
959                 }
960                 return ES_R_ERROR;
961         }
962
963         s_info.client = client;
964
965         _D("ESD init done\n");
966
967         return 0;
968 }
969
970 static void esd_remove_app_list(gpointer data, gpointer user_data)
971 {
972         esd_list_item_s *item = (esd_list_item_s *)data;
973
974         free(item->app_id);
975         free(item->pkg_id);
976 }
977
978 static void esd_finalize(void)
979 {
980         gpointer key, value;
981         int ret = 0;
982
983         _D("esd finalize");
984
985 #ifdef APPFW_EVENT_SYSTEM_EARLIER_FEATURE
986         if (earlier_event_table) {
987                 GHashTableIter iter;
988
989                 g_hash_table_iter_init(&iter, earlier_event_table);
990
991                 while (g_hash_table_iter_next(&iter, &key, &value)) {
992                         earlier_item *item = (earlier_item *)value;
993                         if (item) {
994                                 eventsystem_unregister_event(item->reg_id);
995                                 free(item->event_name);
996                                 bundle_free(item->earlier_data);
997                                 free(item);
998                         } else {
999                                 LOGE("item is NULL");
1000                         }
1001                         g_hash_table_iter_remove(&iter);
1002                 }
1003                 g_hash_table_unref(earlier_event_table);
1004         }
1005 #endif
1006
1007         if (event_launch_table) {
1008                 GHashTableIter iter;
1009
1010                 g_hash_table_iter_init(&iter, event_launch_table);
1011
1012                 while (g_hash_table_iter_next(&iter, &key, &value)) {
1013                         event_launch_item *el_item = (event_launch_item *)value;
1014                         if (el_item) {
1015                                 eventsystem_unregister_event(el_item->reg_id);
1016                                 free(el_item->event_name);
1017                                 g_list_foreach(el_item->app_list_evtlaunch,
1018                                         esd_remove_app_list, NULL);
1019                                 g_list_free(el_item->app_list_evtlaunch);
1020                                 free(el_item);
1021                         } else {
1022                                 LOGE("item is NULL");
1023                         }
1024                         g_hash_table_iter_remove(&iter);
1025                 }
1026                 g_hash_table_unref(event_launch_table);
1027         }
1028
1029         if (introspection_data) {
1030                 g_dbus_node_info_unref(introspection_data);
1031         }
1032
1033         if (s_info.client) {
1034                 ret = pkgmgr_client_free(s_info.client);
1035                 if (ret != PKGMGR_R_OK) {
1036                         _E("pkgmgr_client_free failed(%d)", ret);
1037                 }
1038         }
1039 }
1040
1041 int main(int argc, char *argv[])
1042 {
1043         _D("event system daemon : main()\n");
1044
1045         if (__esd_init() != 0) {
1046                 _E("ESD Initialization failed!\n");
1047                 assert(0);
1048                 return ES_R_ERROR;
1049         }
1050
1051         if (__esd_before_loop() < 0) {
1052                 _E("ESD failed!\n");
1053                 esd_finalize();
1054                 assert(0);
1055                 return ES_R_ERROR;
1056         }
1057
1058         ecore_main_loop_begin();
1059
1060         _E("shutdown");
1061
1062         esd_finalize();
1063
1064         ecore_shutdown();
1065
1066         return 0;
1067 }