From 9bcc45a35fc31622a727a56e390ef7251fea40c4 Mon Sep 17 00:00:00 2001 From: "seungha.son" Date: Thu, 5 Jan 2017 22:19:24 +0900 Subject: [PATCH] Implements some function for check busname is existed - Before sending an event to the notification caller using the notification_send_event() API, check if the busname exists. - By using hashtable data-structure, the priv_id of notification_h and the busname are managed. - Check by watching the busname of the app that posted the notification. related with patch : https://review.tizen.org/gerrit/#/c/108771/ API : notification_check_event_sender() Signed-off-by: seungha.son Change-Id: Ie92a1c5e7ac46cc4d2aa2902f35043861f65c814 --- include/notification_service.h | 2 + include/service_common.h | 1 + src/notification_service.c | 254 ++++++++++++++++++++++++++++++----------- src/service_common.c | 4 +- 4 files changed, 191 insertions(+), 70 deletions(-) diff --git a/include/notification_service.h b/include/notification_service.h index 1e9c77d..d7bb89b 100755 --- a/include/notification_service.h +++ b/include/notification_service.h @@ -43,6 +43,8 @@ int notification_get_block_state(GVariant *parameters, GVariant **reply_body, ui int notification_load_dnd_allow_exception(GVariant *parameters, GVariant **reply_body, uid_t uid); int notification_update_dnd_allow_exception(GVariant *parameters, GVariant **reply_body, uid_t uid); int notification_send_noti_event(GVariant *parameters, GVariant **reply_body); +int notification_check_event_receiver(GVariant *parameters, GVariant **reply_body); +int notification_reset_event_receiver(GVariant *parameters, GVariant **reply_body, const char *sender); int notification_register_dbus_interface(); int notification_delete_noti_by_appid(const char *appid, uid_t uid); diff --git a/include/service_common.h b/include/service_common.h index a44d8c1..629b67b 100755 --- a/include/service_common.h +++ b/include/service_common.h @@ -50,6 +50,7 @@ typedef struct monitoring_info { void print_noti(notification_h noti); int send_notify(GVariant *body, char *cmd, GHashTable **monitoring_hash, char *interface_name, uid_t uid); +bool is_existed_busname(const char *sender_name); int send_event_notify_by_busname(GVariant *body, char *cmd, char *busname, char *interface_name); int service_register(GVariant *parameters, GVariant **reply_body, const gchar *sender, GBusNameAppearedCallback name_appeared_handler, diff --git a/src/notification_service.c b/src/notification_service.c index 2eb857e..dec37e3 100755 --- a/src/notification_service.c +++ b/src/notification_service.c @@ -55,11 +55,12 @@ typedef struct _dnd_alarm_id { alarm_id_t dnd_end_id; } dnd_alarm_id_s; -static GHashTable *__event_sender_hash; +static GList *__event_list = NULL; typedef struct _event_sender_info { int priv_id; char *busname; + guint watcher_id; } event_sender_info_s; /*! @@ -158,6 +159,10 @@ static void _noti_dbus_method_call_handler(GDBusConnection *conn, ret = notification_update_dnd_allow_exception(parameters, &reply_body, uid); else if (g_strcmp0(method_name, "send_noti_event") == 0) ret = notification_send_noti_event(parameters, &reply_body); + else if (g_strcmp0(method_name, "check_event_receiver") == 0) + ret = notification_check_event_receiver(parameters, &reply_body); + else if (g_strcmp0(method_name, "reset_event_handler") == 0) + ret = notification_reset_event_receiver(parameters, &reply_body, sender); if (ret == NOTIFICATION_ERROR_NONE) { DbgPrint("notification service success : %d", ret); @@ -335,6 +340,15 @@ int notification_register_dbus_interface() " " " " + " " + " " + " " + " " + + " " + " " + " " + " " " " " " @@ -343,7 +357,7 @@ int notification_register_dbus_interface() return service_common_register_dbus_interface(introspection_xml, _noti_interface_vtable); } -static void __free_event_list(gpointer data) +static void __free_event_info(gpointer data) { event_sender_info_s *info = (event_sender_info_s *)data; @@ -468,51 +482,103 @@ static int _validate_and_set_param_uid_with_uid(uid_t uid, uid_t *param_uid) return ret; } -static int __add_sender_info(int priv_id, const char *busname, uid_t uid) +static void __sender_name_appeared_cb(GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + DbgPrint("sender name appeared name: %s, name_owner : %s", name, name_owner); +} + +static void __sender_name_vanished_cb(GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + GList *delete_list = NULL; + event_sender_info_s *info; + + if (!user_data) + return; + + info = (event_sender_info_s *)user_data; + + DbgPrint("sender name vanished name : %s, priv_id : %d, watcher_id : %d", + name, info->priv_id, info->watcher_id); + + delete_list = g_list_find_custom(__event_list, GUINT_TO_POINTER(info->priv_id), + (GCompareFunc)__priv_id_compare); + if (delete_list) { + __event_list = g_list_remove(__event_list, info); + g_bus_unwatch_name(info->watcher_id); + __free_event_info(info); + } +} + +static guint __insert_sender_watcher_id(event_sender_info_s *sender_info) +{ + guint watcher_id = 0; + watcher_id = g_bus_watch_name(G_BUS_TYPE_SYSTEM, + sender_info->busname, + G_BUS_NAME_WATCHER_FLAGS_NONE, + __sender_name_appeared_cb, + __sender_name_vanished_cb, + sender_info, + NULL); + if (!watcher_id) { + ErrPrint("fail to watch sender name"); + return 0; + } + + DbgPrint("watch on %s success - watcher_id : %d", sender_info->busname, watcher_id); + return watcher_id; +} + +static void __add_sender_info(int priv_id, const char *busname) { - GList *event_list = NULL; GList *find_list = NULL; event_sender_info_s *sender_info; event_sender_info_s *tmp_info = NULL; - if (__event_sender_hash == NULL) - __event_sender_hash = g_hash_table_new(g_direct_hash, g_direct_equal); - - event_list = g_hash_table_lookup(__event_sender_hash, GUINT_TO_POINTER(uid)); + if (busname == NULL) + return; sender_info = (event_sender_info_s *)malloc(sizeof(event_sender_info_s)); if (sender_info == NULL) { - DbgPrint("malloc failed"); - return NOTIFICATION_ERROR_OUT_OF_MEMORY; + ErrPrint("malloc failed"); + return; } sender_info->priv_id = priv_id; sender_info->busname = strdup(busname); - if (event_list == NULL) { - event_list = g_list_append(event_list, sender_info); - g_hash_table_insert(__event_sender_hash, GUINT_TO_POINTER(uid), event_list); + if (__event_list == NULL) { + sender_info->watcher_id = __insert_sender_watcher_id(sender_info); + __event_list = g_list_append(__event_list, sender_info); } else { - event_list = g_list_first(event_list); - find_list = g_list_find_custom(event_list, GUINT_TO_POINTER(priv_id), + __event_list = g_list_first(__event_list); + find_list = g_list_find_custom(__event_list, GUINT_TO_POINTER(priv_id), (GCompareFunc)__priv_id_compare); if (find_list == NULL) { - event_list = g_list_append(event_list, sender_info); + sender_info->watcher_id = __insert_sender_watcher_id(sender_info); + __event_list = g_list_append(__event_list, sender_info); } else { tmp_info = (event_sender_info_s *)g_list_nth_data(find_list, 0); - if (tmp_info->busname) - free(tmp_info->busname); - tmp_info->busname = strdup(busname); - - if (sender_info) { - if (sender_info->busname) - free(sender_info->busname); - free(sender_info); + if (tmp_info->busname) { + if (strcmp(tmp_info->busname, busname)) { + free(tmp_info->busname); + tmp_info->busname = strdup(busname); + g_bus_unwatch_name(tmp_info->watcher_id); + tmp_info->watcher_id = __insert_sender_watcher_id(sender_info); + } + } else { + tmp_info->busname = strdup(busname); + if (!tmp_info->watcher_id) + g_bus_unwatch_name(tmp_info->watcher_id); + tmp_info->watcher_id = __insert_sender_watcher_id(tmp_info); } + __free_event_info(sender_info); } } - - return NOTIFICATION_ERROR_NONE; } int notification_add_noti(GVariant *parameters, GVariant **reply_body, const char *sender, uid_t uid) @@ -549,7 +615,7 @@ int notification_add_noti(GVariant *parameters, GVariant **reply_body, const cha if (ret != NOTIFICATION_ERROR_NONE) return ret; - __add_sender_info(priv_id, sender, noti_uid); + __add_sender_info(priv_id, sender); } notification_free(noti); } else { @@ -947,22 +1013,16 @@ int notification_refresh_noti(GVariant *parameters, GVariant **reply_body, uid_t return ret; } -static int __delete_sender_info(int priv_id, uid_t uid) +static int __delete_sender_info(int priv_id) { int ret = NOTIFICATION_ERROR_NONE; event_sender_info_s *info; - GList *event_list = NULL; GList *delete_list = NULL; GVariant *body = NULL; - if (__event_sender_hash == NULL) - return NOTIFICATION_ERROR_NONE; - - event_list = g_hash_table_lookup(__event_sender_hash, GUINT_TO_POINTER(uid)); - - if (event_list != NULL) { - event_list = g_list_first(event_list); - delete_list = g_list_find_custom(event_list, GUINT_TO_POINTER(priv_id), + if (__event_list != NULL) { + __event_list = g_list_first(__event_list); + delete_list = g_list_find_custom(__event_list, GUINT_TO_POINTER(priv_id), (GCompareFunc)__priv_id_compare); if (delete_list != NULL) { info = (event_sender_info_s *)g_list_nth_data(delete_list, 0); @@ -973,9 +1033,11 @@ static int __delete_sender_info(int priv_id, uid_t uid) ErrPrint("failed to send event notify:%d\n", ret); return ret; } - event_list = g_list_remove(g_list_first(event_list), info); - __free_event_list(info); - g_hash_table_replace(__event_sender_hash, GUINT_TO_POINTER(uid), event_list); + __event_list = g_list_remove(g_list_first(__event_list), info); + g_bus_unwatch_name(info->watcher_id); + __free_event_info(info); + if (g_list_length(__event_list) == 0) + __event_list = NULL; } } @@ -1016,7 +1078,7 @@ int notification_del_noti_single(GVariant *parameters, GVariant **reply_body, ui return ret; } - ret = __delete_sender_info(priv_id, uid); + ret = __delete_sender_info(priv_id); if (ret != NOTIFICATION_ERROR_NONE) return ret; } @@ -1076,7 +1138,7 @@ int notification_del_noti_multiple(GVariant *parameters, GVariant **reply_body, } for (i = 0; i < num_deleted; i++) { - ret = __delete_sender_info(*(list_deleted + i), param_uid); + ret = __delete_sender_info(*(list_deleted + i)); if (ret != NOTIFICATION_ERROR_NONE) return ret; } @@ -1733,32 +1795,24 @@ int notification_update_dnd_allow_exception(GVariant *parameters, GVariant **rep return ret; } -static char *__find_busname_by_priv_id(int priv_id, uid_t uid) +static event_sender_info_s *__find_sender_info_by_priv_id(int priv_id) { - char *busname = NULL; event_sender_info_s *event_info; - GList *event_list; GList *find_list; - if (__event_sender_hash == NULL) + if (__event_list == NULL) return NULL; - event_list = g_hash_table_lookup(__event_sender_hash, GUINT_TO_POINTER(uid)); - if (event_list == NULL) - return NULL; - - event_list = g_list_first(event_list); - find_list = g_list_find_custom(event_list, GUINT_TO_POINTER(priv_id), + __event_list = g_list_first(__event_list); + find_list = g_list_find_custom(__event_list, GUINT_TO_POINTER(priv_id), (GCompareFunc)__priv_id_compare); - if (find_list) { + if (find_list) event_info = g_list_nth_data(find_list, 0); - busname = strdup(event_info->busname); - } else { + else return NULL; - } - return busname; + return event_info; } int notification_send_noti_event(GVariant *parameters, GVariant **reply_body) @@ -1766,11 +1820,10 @@ int notification_send_noti_event(GVariant *parameters, GVariant **reply_body) int ret; int event_type; int priv_id; - char *busname = NULL; + event_sender_info_s *info; GVariant *coupled_body = NULL; GVariant *body = NULL; notification_h noti; - uid_t noti_uid; noti = notification_create(NOTIFICATION_TYPE_NOTI); @@ -1791,17 +1844,23 @@ int notification_send_noti_event(GVariant *parameters, GVariant **reply_body) if (ret != NOTIFICATION_ERROR_NONE) return ret; - ret = notification_get_uid(noti, ¬i_uid); - if (ret != NOTIFICATION_ERROR_NONE) - return ret; - - busname = __find_busname_by_priv_id(priv_id, noti_uid); - if (busname == NULL) + info = __find_sender_info_by_priv_id(priv_id); + if (info == NULL || info->busname == NULL) return NOTIFICATION_ERROR_INVALID_PARAMETER; - ret = send_event_notify_by_busname(parameters, "send_event", busname, PROVIDER_NOTI_EVENT_INTERFACE_NAME); + if (!info->watcher_id) { + if (!is_existed_busname(info->busname)) { + __event_list = g_list_remove(g_list_first(__event_list), info); + __free_event_info(info); + return NOTIFICATION_ERROR_IO_ERROR; + } else { + info->watcher_id = __insert_sender_watcher_id(info); + } + } + + ret = send_event_notify_by_busname(parameters, "send_event", info->busname, PROVIDER_NOTI_EVENT_INTERFACE_NAME); notification_free(noti); - free(busname); + } else { ret = NOTIFICATION_ERROR_OUT_OF_MEMORY; } @@ -1811,9 +1870,68 @@ int notification_send_noti_event(GVariant *parameters, GVariant **reply_body) ErrPrint("cannot make reply body"); return NOTIFICATION_ERROR_OUT_OF_MEMORY; } + + DbgPrint("notification_send_noti_event done !! %d", ret); + return ret; } +int notification_check_event_receiver(GVariant *parameters, GVariant **reply_body) +{ + int priv_id; + bool available = false; + GList *find_list = NULL; + event_sender_info_s *info = NULL; + + g_variant_get(parameters, "(i)", &priv_id); + DbgPrint("check event sender - priv_id : %d", priv_id); + + __event_list = g_list_first(__event_list); + find_list = g_list_find_custom(__event_list, GUINT_TO_POINTER(priv_id), + (GCompareFunc)__priv_id_compare); + if (find_list) { + info = g_list_nth_data(find_list, 0); + if (!info->watcher_id) { + if (!is_existed_busname(info->busname)) { + __event_list = g_list_remove(g_list_first(__event_list), info); + __free_event_info(info); + } else { + available = true; + info->watcher_id = __insert_sender_watcher_id(info); + } + } else { + available = true; + } + } + + *reply_body = g_variant_new("(i)", (int)available); + if (*reply_body == NULL) { + ErrPrint("cannot make gvariant to noti"); + return NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + + DbgPrint("notification check event receiver - available[%d]", available); + return NOTIFICATION_ERROR_NONE; +} + +int notification_reset_event_receiver(GVariant *parameters, GVariant **reply_body, const char *sender) +{ + int priv_id; + + g_variant_get(parameters, "(i)", &priv_id); + DbgPrint("reset event sender - priv_id : %d", priv_id); + + __add_sender_info(priv_id, sender); + + *reply_body = g_variant_new("()"); + if (*reply_body == NULL) { + ErrPrint("cannot make gvariant to noti"); + return NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + + return NOTIFICATION_ERROR_NONE; +} + HAPI int notification_delete_noti_by_appid(const char *appid, uid_t uid) { GVariant *deleted_noti_list; @@ -1847,7 +1965,7 @@ HAPI int notification_delete_noti_by_appid(const char *appid, uid_t uid) } for (i = 0; i < num_deleted; i++) { - ret = __delete_sender_info(*(list_deleted + i), uid); + ret = __delete_sender_info(*(list_deleted + i)); if (ret != NOTIFICATION_ERROR_NONE) return ret; } diff --git a/src/service_common.c b/src/service_common.c index 79a15e9..8535d21 100755 --- a/src/service_common.c +++ b/src/service_common.c @@ -141,7 +141,7 @@ out: return pid; } -static bool _is_existed_busname(const char *sender_name) +bool is_existed_busname(const char *sender_name) { GDBusMessage *msg = NULL; GDBusMessage *reply = NULL; @@ -216,7 +216,7 @@ int send_notify(GVariant *body, char *cmd, GHashTable **monitoring_hash, char *i err->message); g_error_free(err); } - is_existed = _is_existed_busname(target_bus_name); + is_existed = is_existed_busname(target_bus_name); if (is_existed == false) delete_monitoring_list(monitoring_hash, target_bus_name, uid); ErrPrint("failed to emit signal: %s", target_bus_name); -- 2.7.4