Add option to execute unittest in building package
[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 extern GMainLoop *main_loop;
33
34 int stickerd_server_register(GVariant *parameters, GVariant **reply_body, const gchar *sender, GBusNameAppearedCallback name_appeared_handler,
35         GBusNameVanishedCallback name_vanished_handler, GHashTable **monitoring_hash, GList **consumer_list)
36 {
37     int ret = STICKERD_SERVER_ERROR_NONE;
38     char *m_info_bus_name = NULL;
39     char *list_bus_name = NULL;
40     monitoring_info_s *m_info = NULL;
41     GList *monitoring_list = NULL;
42     int c_lib;
43
44     g_variant_get(parameters, "(i)", &c_lib);
45
46     if (reply_body == NULL)
47         return STICKERD_SERVER_ERROR_INVALID_PARAMETER;
48
49     m_info_bus_name = strdup(sender);
50     list_bus_name = strdup(sender);
51     if (m_info_bus_name == NULL || list_bus_name == NULL) {
52         ret = STICKERD_SERVER_ERROR_IO_ERROR;
53         goto cleanup;
54     }
55
56     LOGD("Add a new sender");
57     m_info = (monitoring_info_s *)calloc(1, sizeof(monitoring_info_s));
58     if (m_info == NULL) {
59         LOGE("Failed to alloc memory");
60         ret = STICKERD_SERVER_ERROR_OUT_OF_MEMORY;
61         goto cleanup;
62     }
63
64     m_info->bus_name = m_info_bus_name;
65     m_info->watcher_id = g_bus_watch_name_on_connection(
66             _gdbus_connection,
67             m_info_bus_name,
68             G_BUS_NAME_WATCHER_FLAGS_NONE,
69             name_appeared_handler,
70             name_vanished_handler,
71             m_info,
72             NULL);
73     if (m_info->watcher_id == 0) {
74         LOGE("Failed to get identifier");
75         ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
76         goto cleanup;
77     }
78
79     *reply_body = g_variant_new("(i)", m_info->watcher_id);
80     if (*reply_body == NULL) {
81         LOGE("Failed to make reply");
82         ret = STICKERD_SERVER_ERROR_OUT_OF_MEMORY;
83         goto cleanup;
84     }
85
86     if ((CLIENT_LIB)c_lib == STICKER_CLIENT_LIB_CONSUMER)
87         *consumer_list = g_list_append(*consumer_list, g_strdup((sender)));
88
89     LOGD("sender: %s, watcher: %d", sender, m_info->watcher_id);
90     monitoring_list = g_list_append(monitoring_list, list_bus_name);
91     if (g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(m_info->watcher_id)) == NULL)
92         g_hash_table_insert(*monitoring_hash, GUINT_TO_POINTER(m_info->watcher_id), monitoring_list);
93     else
94         LOGW("Sender(%s) already exist", sender);
95
96     return STICKERD_SERVER_ERROR_NONE;
97
98 cleanup:
99     if (m_info_bus_name)
100         free(m_info_bus_name);
101
102     if (list_bus_name)
103         free(list_bus_name);
104
105     if (m_info) {
106         free(m_info);
107         m_info = NULL;
108     }
109
110     return ret;
111 }
112
113 int stickerd_server_unregister(GVariant *parameters, GVariant **reply_body, const gchar *sender, GHashTable **monitoring_hash, GList **consumer_list)
114 {
115     int watcher_id = 0;
116     int c_lib;
117
118     g_variant_get(parameters, "(ii)", &c_lib, &watcher_id);
119
120     if ((CLIENT_LIB)c_lib == STICKER_CLIENT_LIB_CONSUMER) {
121         GList *node = g_list_find_custom(*consumer_list, sender, (GCompareFunc) strcmp);
122         if (node)
123             *consumer_list = g_list_delete_link(*consumer_list, node);
124     }
125
126     if (g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(watcher_id)) != NULL) {
127         g_bus_unwatch_name(watcher_id);
128         delete_monitoring_list(monitoring_hash, sender, watcher_id);
129     }
130
131     return STICKERD_SERVER_ERROR_NONE;
132 }
133
134 int stickerd_server_register_dbus_interface(char *introspection_xml, GDBusInterfaceVTable interface_vtable)
135 {
136     int result;
137     int own_id, registration_id;
138     GError *error = NULL;
139     GDBusNodeInfo *introspection_data = NULL;
140
141     if (_gdbus_connection == NULL) {
142         _gdbus_connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
143         if (_gdbus_connection == NULL) {
144             if (error != NULL) {
145                 LOGE("g_bus_get_sync error message = %s", error->message);
146                 g_error_free(error);
147             }
148             result = STICKERD_SERVER_ERROR_IO_ERROR;
149             goto cleanup;
150         }
151     }
152
153     own_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
154             STICKER_DBUS_NAME,
155             G_BUS_NAME_OWNER_FLAGS_NONE,
156             NULL,
157             NULL,
158             NULL,
159             NULL, NULL);
160     if (own_id == 0) {
161         LOGE("Failed to register bus name");
162         result = STICKERD_SERVER_ERROR_IO_ERROR;
163         goto cleanup;
164     }
165
166     LOGD("own_id = %d", own_id);
167
168     introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, &error);
169     if (introspection_data == NULL) {
170         LOGE("Failed to get GDBusNodeInfo");
171         result = STICKERD_SERVER_ERROR_IO_ERROR;
172         if (error != NULL) {
173             LOGE("g_dbus_node_info_new_for_xml error message = %s", error->message);
174             g_error_free(error);
175         }
176         goto cleanup;
177     }
178
179     registration_id = g_dbus_connection_register_object(_gdbus_connection, STICKER_OBJECT_PATH,
180         introspection_data->interfaces[0], &interface_vtable, NULL, NULL, NULL);
181     LOGD("registration_id = %d", registration_id);
182     if (registration_id == 0) {
183         LOGE("Failed to register object");
184         result = STICKERD_SERVER_ERROR_IO_ERROR;
185         goto cleanup;
186     }
187
188     return STICKERD_SERVER_ERROR_NONE;
189
190 cleanup:
191     if (introspection_data)
192         g_dbus_node_info_unref(introspection_data);
193
194     return result;
195 }
196
197 int delete_monitoring_list(GHashTable **monitoring_hash, const char *sender, int watcher_id)
198 {
199     GList *monitoring_list = NULL;
200     GList *del_list = NULL;
201     char *bus_name;
202
203     monitoring_list = (GList *)g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(watcher_id));
204     if (monitoring_list == NULL) {
205         LOGE("The key(%d) is not found", watcher_id);
206         return STICKERD_SERVER_ERROR_IO_ERROR;
207     }
208
209     monitoring_list = g_list_first(monitoring_list);
210     del_list = g_list_find_custom(monitoring_list, sender, (GCompareFunc) strcmp);
211
212     if (del_list) {
213         LOGD("Delete sender(%s)", sender);
214         bus_name = g_list_nth_data(del_list, 0);
215         if (bus_name)
216             free(bus_name);
217         monitoring_list = g_list_delete_link(monitoring_list, del_list);
218
219         if (monitoring_list == NULL) {
220             g_hash_table_steal(*monitoring_hash, GUINT_TO_POINTER(watcher_id));
221         } else {
222             monitoring_list = g_list_first(monitoring_list);
223             g_hash_table_replace(*monitoring_hash, GUINT_TO_POINTER(watcher_id), monitoring_list);
224         }
225     }
226     return STICKERD_SERVER_ERROR_NONE;
227 }
228
229 int stickerd_send_dbus_message(GVariant *body, const char *dest, char *cmd, CLIENT_LIB lib)
230 {
231     GError *err = NULL;
232     char *interface = NULL;
233
234     if (lib == STICKER_CLIENT_LIB_PROVIDER)
235         interface = STICKER_PROVIDER_INTERFACE_NAME;
236     else if (lib == STICKER_CLIENT_LIB_CONSUMER)
237         interface = STICKER_CONSUMER_INTERFACE_NAME;
238
239     if (g_variant_is_floating(body))
240         g_variant_ref(body);
241
242     if (!g_dbus_connection_emit_signal(_gdbus_connection,
243                                       dest,
244                                       STICKER_OBJECT_PATH,
245                                       interface,
246                                       cmd,
247                                       body,
248                                       &err)) {
249         if (err != NULL) {
250             LOGE("Failed to send dbus message : %s", err->message);
251             g_error_free(err);
252         }
253
254         return STICKERD_SERVER_ERROR_IO_ERROR;
255     }
256
257     LOGD("Send message to client : %s", cmd);
258     return STICKERD_SERVER_ERROR_NONE;
259 }