Initial commit
[platform/core/uifw/capi-ui-sticker.git] / server / stickerd_dbus.c
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <gio/gio.h>
21 #include <dlog.h>
22
23 #include "stickerd_dbus.h"
24 #include "stickerd_error.h"
25
26 #ifdef LOG_TAG
27 #undef LOG_TAG
28 #endif
29 #define LOG_TAG "STICKERD_DBUS"
30
31 static GDBusConnection *_gdbus_connection;
32
33 int stickerd_server_register(GVariant *parameters, GVariant **reply_body, const gchar *sender, GBusNameAppearedCallback name_appeared_handler,
34         GBusNameVanishedCallback name_vanished_handler, GHashTable **monitoring_hash)
35 {
36     GList *sender_list = NULL;
37     const char *bus_name = sender;
38     monitoring_info_s *m_info = NULL;
39     uid_t request_uid = 0;
40     GList *monitoring_list = NULL;
41
42     if (bus_name == NULL)
43         return STICKERD_SERVER_ERROR_IO_ERROR;
44
45     g_variant_get(parameters, "(i)", &request_uid);
46     monitoring_list = (GList *)g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(request_uid));
47     sender_list = g_list_find_custom(monitoring_list, bus_name, (GCompareFunc) strcmp);
48
49     if (sender_list == NULL) {
50         LOGD("Add a new sender");
51         m_info = (monitoring_info_s *)calloc(1, sizeof(monitoring_info_s));
52         if (m_info == NULL) {
53             LOGE("Failed to alloc memory");
54             return STICKERD_SERVER_ERROR_IO_ERROR;
55         }
56
57         m_info->bus_name = strdup(bus_name);
58         m_info->uid = request_uid;
59         m_info->watcher_id = g_bus_watch_name_on_connection(
60                 _gdbus_connection,
61                 bus_name,
62                 G_BUS_NAME_WATCHER_FLAGS_NONE,
63                 name_appeared_handler,
64                 name_vanished_handler,
65                 m_info,
66                 NULL);
67         if (m_info->watcher_id == 0) {
68             LOGE("Failed to get identifier");
69             free(m_info->bus_name);
70             free(m_info);
71             return STICKERD_SERVER_ERROR_IO_ERROR;
72         }
73
74         monitoring_list = g_list_append(monitoring_list, strdup(bus_name));
75         LOGD("sender: %s, len: %d", sender, g_list_length(monitoring_list));
76         if (g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(request_uid)) == NULL)
77             g_hash_table_insert(*monitoring_hash, GUINT_TO_POINTER(request_uid), monitoring_list);
78     } else {
79         LOGW("Sender(%s) already exist", sender);
80     }
81
82     *reply_body = g_variant_new("()");
83     if (*reply_body == NULL) {
84         if (m_info) {
85             if (m_info->bus_name)
86                 free(m_info->bus_name);
87             free(m_info);
88         }
89         monitoring_list = g_list_remove(monitoring_list, bus_name);
90         LOGE("Failed to make reply");
91         return STICKERD_SERVER_ERROR_OUT_OF_MEMORY;
92     }
93     return STICKERD_SERVER_ERROR_NONE;
94 }
95
96 int stickerd_server_register_dbus_interface(char *introspection_xml, GDBusInterfaceVTable interface_vtable)
97 {
98     int result;
99     int own_id, registration_id;
100     GError *error = NULL;
101     GDBusNodeInfo *introspection_data = NULL;
102
103     if (_gdbus_connection == NULL) {
104         _gdbus_connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
105         if (_gdbus_connection == NULL) {
106             if (error != NULL) {
107                 LOGE("g_bus_get_sync error message = %s", error->message);
108                 g_error_free(error);
109             }
110             result = STICKERD_SERVER_ERROR_IO_ERROR;
111             goto cleanup;
112         }
113     }
114
115     own_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
116             STICKER_DBUS_NAME,
117             G_BUS_NAME_OWNER_FLAGS_NONE,
118             NULL,
119             NULL,
120             NULL,
121             NULL, NULL);
122     if (own_id == 0) {
123         LOGE("Failed to register bus name");
124         result = STICKERD_SERVER_ERROR_IO_ERROR;
125         goto cleanup;
126     }
127
128     LOGD("own_id = %d", own_id);
129
130     introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, &error);
131     if (introspection_data == NULL) {
132         LOGE("Failed to get GDBusNodeInfo");
133         result = STICKERD_SERVER_ERROR_IO_ERROR;
134         if (error != NULL) {
135             LOGE("g_dbus_node_info_new_for_xml error message = %s", error->message);
136             g_error_free(error);
137         }
138         goto cleanup;
139     }
140
141     registration_id = g_dbus_connection_register_object(_gdbus_connection, STICKER_OBJECT_PATH,
142         introspection_data->interfaces[0], &interface_vtable, NULL, NULL, NULL);
143     LOGD("registration_id = %d", registration_id);
144     if (registration_id == 0) {
145         LOGE("Failed to register object");
146         result = STICKERD_SERVER_ERROR_IO_ERROR;
147         goto cleanup;
148     }
149
150     return STICKERD_SERVER_ERROR_NONE;
151
152 cleanup:
153     if (introspection_data)
154         g_dbus_node_info_unref(introspection_data);
155
156     return result;
157 }
158
159 int delete_monitoring_list(GHashTable **monitoring_hash, const char *sender, uid_t uid)
160 {
161     GList *monitoring_list = NULL;
162     GList *del_list = NULL;
163     char *bus_name;
164
165     monitoring_list = (GList *)g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(uid));
166     if (monitoring_list == NULL) {
167         LOGE("The key(%d) is not found", uid);
168         return STICKERD_SERVER_ERROR_IO_ERROR;
169     }
170
171     monitoring_list = g_list_first(monitoring_list);
172     del_list = g_list_find_custom(monitoring_list, sender, (GCompareFunc) strcmp);
173
174     if (del_list) {
175         LOGD("Delete sender(%s)", sender);
176         bus_name = g_list_nth_data(del_list, 0);
177         if (bus_name)
178             free(bus_name);
179         monitoring_list = g_list_delete_link(monitoring_list, del_list);
180
181         if (monitoring_list == NULL) {
182             g_hash_table_steal(*monitoring_hash, GUINT_TO_POINTER(uid));
183         } else {
184             monitoring_list = g_list_first(monitoring_list);
185             g_hash_table_replace(*monitoring_hash, GUINT_TO_POINTER(uid), monitoring_list);
186         }
187     }
188     return STICKERD_SERVER_ERROR_NONE;
189 }
190
191 int stickerd_send_dbus_message(GVariant *body, const char *dest, char *cmd, CLIENT_LIB lib)
192 {
193     GError *err = NULL;
194     char *interface = NULL;
195
196     if (lib == STICKER_CLIENT_LIB_PROVIDER)
197         interface = STICKER_PROVIDER_INTERFACE_NAME;
198     else if (lib == STICKER_CLIENT_LIB_CONSUMER)
199         interface = STICKER_CONSUMER_INTERFACE_NAME;
200
201     if (g_variant_is_floating(body))
202         g_variant_ref(body);
203
204     if (!g_dbus_connection_emit_signal(_gdbus_connection,
205                                       dest,
206                                       STICKER_OBJECT_PATH,
207                                       interface,
208                                       cmd,
209                                       body,
210                                       &err)) {
211         if (err != NULL) {
212             LOGE("Failed to send dbus message : %s", err->message);
213             g_error_free(err);
214         }
215
216         return STICKERD_SERVER_ERROR_IO_ERROR;
217     }
218
219     LOGD("Send message to client : %s", cmd);
220     return STICKERD_SERVER_ERROR_NONE;
221 }