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