Implements some function for check busname is existed 70/108770/8
authorseungha.son <seungha.son@samsung.com>
Thu, 5 Jan 2017 13:19:24 +0000 (22:19 +0900)
committerseungha.son <seungha.son@samsung.com>
Wed, 11 Jan 2017 04:37:23 +0000 (13:37 +0900)
 - 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 <seungha.son@samsung.com>
Change-Id: Ie92a1c5e7ac46cc4d2aa2902f35043861f65c814

include/notification_service.h
include/service_common.h
src/notification_service.c
src/service_common.c

index 1e9c77d..d7bb89b 100755 (executable)
@@ -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);
 
index a44d8c1..629b67b 100755 (executable)
@@ -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,
index 2eb857e..dec37e3 100755 (executable)
@@ -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()
                        "          <arg type='i' name='event_type' direction='in'/>"
                        "        </method>"
 
+                       "        <method name='check_event_receiver'>"
+                       "          <arg type='i' name='priv_id' direction='in'/>"
+                       "          <arg type='i' name='available' direction='out'/>"
+                       "        </method>"
+
+                       "        <method name='reset_event_handler'>"
+                       "          <arg type='i' name='priv_id' direction='in'/>"
+                       "        </method>"
+
                        "        <method name='post_toast'>"
                        "        </method>"
                        "  </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, &noti_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;
                }
index 79a15e9..8535d21 100755 (executable)
@@ -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);