3047aecc52b5395e0c5c200f2b18b75d622cd1f5
[platform/core/system/tlm.git] / src / daemon / dbus / tlm-dbus-login-adapter.c
1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4  * This file is part of tlm
5  *
6  * Copyright (C) 2014 Intel Corporation.
7  *
8  * Contact: Imran Zaman <imran.zaman@intel.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23  * 02110-1301 USA
24  */
25
26 #include "config.h"
27
28 #include "common/tlm-log.h"
29 #include "common/tlm-error.h"
30 #include "common/dbus/tlm-dbus.h"
31
32 #include "tlm-dbus-login-adapter.h"
33
34 enum
35 {
36     PROP_0,
37
38     PROP_CONNECTION,
39
40     N_PROPERTIES
41 };
42
43 static GParamSpec *properties[N_PROPERTIES];
44
45 struct _TlmDbusLoginAdapterPrivate
46 {
47     GDBusConnection *connection;
48     TlmDbusLogin *dbus_obj;
49 };
50
51 G_DEFINE_TYPE (TlmDbusLoginAdapter, tlm_dbus_login_adapter, G_TYPE_OBJECT)
52
53 #define TLM_DBUS_LOGIN_ADAPTER_GET_PRIV(obj) \
54     G_TYPE_INSTANCE_GET_PRIVATE ((obj), TLM_TYPE_LOGIN_ADAPTER, \
55             TlmDbusLoginAdapterPrivate)
56
57 enum {
58     SIG_LOGIN_USER,
59     SIG_LOGOUT_USER,
60     SIG_SWITCH_USER,
61
62     SIG_MAX
63 };
64
65 static guint signals[SIG_MAX];
66
67 static gboolean
68 _handle_login_user (
69         TlmDbusLoginAdapter *self,
70         GDBusMethodInvocation *invocation,
71         const gchar *seat_id,
72         const gchar *username,
73         const gchar *password,
74         const GVariant *environ,
75         gpointer user_data);
76
77 static gboolean
78 _handle_switch_user (
79         TlmDbusLoginAdapter *self,
80         GDBusMethodInvocation *invocation,
81         const gchar *seat_id,
82         const gchar *username,
83         const gchar *password,
84         const GVariant *environ,
85         gpointer user_data);
86
87 static gboolean
88 _handle_logout_user (
89         TlmDbusLoginAdapter *self,
90         GDBusMethodInvocation *invocation,
91         const gchar *seat_id,
92         gpointer user_data);
93
94 static void
95 _set_property (
96         GObject *object,
97         guint property_id,
98         const GValue *value,
99         GParamSpec *pspec)
100 {
101     TlmDbusLoginAdapter *self = TLM_DBUS_LOGIN_ADAPTER (object);
102
103     switch (property_id) {
104         case PROP_CONNECTION:
105             self->priv->connection = g_value_dup_object (value);
106             break;
107         default:
108             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
109     }
110 }
111
112 static void
113 _get_property (
114         GObject *object,
115         guint property_id,
116         GValue *value,
117         GParamSpec *pspec)
118 {
119     TlmDbusLoginAdapter *self = TLM_DBUS_LOGIN_ADAPTER (object);
120
121     switch (property_id) {
122         case PROP_CONNECTION:
123             g_value_set_object (value, self->priv->connection);
124             break;
125         default:
126             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
127     }
128 }
129
130 static void
131 _dispose (
132         GObject *object)
133 {
134     TlmDbusLoginAdapter *self = TLM_DBUS_LOGIN_ADAPTER (object);
135
136     DBG("- unregistering dbus login adaptor %p.", self);
137
138     if (self->priv->dbus_obj) {
139         g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (
140                 self->priv->dbus_obj));
141         g_object_unref (self->priv->dbus_obj);
142         self->priv->dbus_obj = NULL;
143     }
144
145     if (self->priv->connection) {
146         /* NOTE: There seems to be some bug in glib's dbus connection's
147          * worker thread such that it does not closes the stream. The problem
148          * is hard to be tracked exactly as it is more of timing issue.
149          * Following code snippet at least closes the stream to avoid any
150          * descriptors leak.
151          * */
152         GIOStream *stream = g_dbus_connection_get_stream (
153                 self->priv->connection);
154         if (stream) g_io_stream_close (stream, NULL, NULL);
155         g_object_unref (self->priv->connection);
156         self->priv->connection = NULL;
157     }
158
159     G_OBJECT_CLASS (tlm_dbus_login_adapter_parent_class)->dispose (
160             object);
161 }
162
163 static void
164 _finalize (
165         GObject *object)
166 {
167
168     G_OBJECT_CLASS (tlm_dbus_login_adapter_parent_class)->finalize (
169             object);
170 }
171
172 static void
173 tlm_dbus_login_adapter_class_init (
174         TlmDbusLoginAdapterClass *klass)
175 {
176     GObjectClass* object_class = G_OBJECT_CLASS (klass);
177
178     g_type_class_add_private (object_class,
179             sizeof (TlmDbusLoginAdapterPrivate));
180
181     object_class->get_property = _get_property;
182     object_class->set_property = _set_property;
183     object_class->dispose = _dispose;
184     object_class->finalize = _finalize;
185
186     properties[PROP_CONNECTION] = g_param_spec_object (
187             "connection",
188             "Bus connection",
189             "DBus connection used",
190             G_TYPE_DBUS_CONNECTION,
191             G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
192
193     g_object_class_install_properties (object_class, N_PROPERTIES, properties);
194
195     signals[SIG_LOGIN_USER] = g_signal_new ("login-user",
196             TLM_TYPE_LOGIN_ADAPTER,
197             G_SIGNAL_RUN_LAST,
198             0,
199             NULL,
200             NULL,
201             NULL,
202             G_TYPE_NONE,
203             5,
204             G_TYPE_STRING,
205             G_TYPE_STRING,
206             G_TYPE_STRING,
207             G_TYPE_VARIANT,
208             G_TYPE_DBUS_METHOD_INVOCATION);
209
210     signals[SIG_LOGOUT_USER] = g_signal_new ("logout-user",
211             TLM_TYPE_LOGIN_ADAPTER,
212             G_SIGNAL_RUN_LAST,
213             0,
214             NULL,
215             NULL,
216             NULL,
217             G_TYPE_NONE,
218             2,
219             G_TYPE_STRING,
220             G_TYPE_DBUS_METHOD_INVOCATION);
221
222     signals[SIG_SWITCH_USER] = g_signal_new ("switch-user",
223             TLM_TYPE_LOGIN_ADAPTER,
224             G_SIGNAL_RUN_LAST,
225             0,
226             NULL,
227             NULL,
228             NULL,
229             G_TYPE_NONE,
230             5,
231             G_TYPE_STRING,
232             G_TYPE_STRING,
233             G_TYPE_STRING,
234             G_TYPE_VARIANT,
235             G_TYPE_DBUS_METHOD_INVOCATION);
236 }
237
238 static void
239 tlm_dbus_login_adapter_init (TlmDbusLoginAdapter *self)
240 {
241     self->priv = TLM_DBUS_LOGIN_ADAPTER_GET_PRIV(self);
242
243     self->priv->connection = 0;
244     self->priv->dbus_obj = tlm_dbus_login_skeleton_new ();
245 }
246
247 static gboolean
248 _handle_login_user (
249         TlmDbusLoginAdapter *self,
250         GDBusMethodInvocation *invocation,
251         const gchar *seat_id,
252         const gchar *username,
253         const gchar *password,
254         const GVariant *environment,
255         gpointer emitter)
256 {
257     GError *error = NULL;
258
259     g_return_val_if_fail (self && TLM_IS_DBUS_LOGIN_ADAPTER(self), FALSE);
260
261     if (!seat_id || !username || !password) {
262         error = TLM_GET_ERROR_FOR_ID (TLM_ERROR_INVALID_INPUT,
263                 "Invalid input");
264         g_dbus_method_invocation_return_gerror (invocation, error);
265         g_error_free (error);
266         return TRUE;
267     }
268     DBG ("Emit login-user signal: seat_id=%s, username=%s", seat_id, username);
269
270     g_signal_emit (self, signals[SIG_LOGIN_USER], 0, seat_id, username,
271             password, environment, invocation);
272
273     return TRUE;
274 }
275
276 static gboolean
277 _handle_logout_user (
278         TlmDbusLoginAdapter *self,
279         GDBusMethodInvocation *invocation,
280         const gchar *seat_id,
281         gpointer emitter)
282 {
283     GError *error = NULL;
284
285     g_return_val_if_fail (self && TLM_IS_DBUS_LOGIN_ADAPTER(self),
286             FALSE);
287
288     if (!seat_id) {
289         error = TLM_GET_ERROR_FOR_ID (TLM_ERROR_INVALID_INPUT,
290                 "Invalid input");
291         g_dbus_method_invocation_return_gerror (invocation, error);
292         g_error_free (error);
293         return TRUE;
294     }
295     DBG ("Emit logout-user signal: seat_id=%s", seat_id);
296
297     g_signal_emit (self, signals[SIG_LOGOUT_USER], 0, seat_id, invocation);
298
299     return TRUE;
300 }
301
302 static gboolean
303 _handle_switch_user (
304         TlmDbusLoginAdapter *self,
305         GDBusMethodInvocation *invocation,
306         const gchar *seat_id,
307         const gchar *username,
308         const gchar *password,
309         const GVariant *environment,
310         gpointer emitter)
311 {
312     GError *error = NULL;
313
314     g_return_val_if_fail (self && TLM_IS_DBUS_LOGIN_ADAPTER(self),
315             FALSE);
316
317     if (!seat_id || !username || !password) {
318         error = TLM_GET_ERROR_FOR_ID (TLM_ERROR_INVALID_INPUT,
319                 "Invalid input");
320         g_dbus_method_invocation_return_gerror (invocation, error);
321         g_error_free (error);
322         return TRUE;
323     }
324     DBG ("Emit switch-user signal: seat_id=%s, username=%s", seat_id, username);
325
326     g_signal_emit (self, signals[SIG_SWITCH_USER], 0, seat_id, username,
327             password, environment, invocation);
328
329     return TRUE;
330 }
331
332 TlmDbusLoginAdapter *
333 tlm_dbus_login_adapter_new_with_connection (
334         GDBusConnection *bus_connection)
335 {
336     GError *err = NULL;
337     TlmDbusLoginAdapter *adapter = TLM_DBUS_LOGIN_ADAPTER (g_object_new (
338             TLM_TYPE_LOGIN_ADAPTER, "connection", bus_connection, NULL));
339
340     if (!g_dbus_interface_skeleton_export (
341             G_DBUS_INTERFACE_SKELETON(adapter->priv->dbus_obj),
342             adapter->priv->connection, TLM_LOGIN_OBJECTPATH, &err)) {
343         WARN ("failed to register object: %s", err->message);
344         g_error_free (err);
345         g_object_unref (adapter);
346         return NULL;
347     }
348
349     DBG("(+) started login interface '%p' at path '%s' on connection"
350             " '%p'", adapter, TLM_LOGIN_OBJECTPATH, bus_connection);
351
352     g_signal_connect_swapped (adapter->priv->dbus_obj,
353         "handle-login-user", G_CALLBACK (_handle_login_user), adapter);
354     g_signal_connect_swapped (adapter->priv->dbus_obj,
355         "handle-logout-user", G_CALLBACK(_handle_logout_user), adapter);
356     g_signal_connect_swapped (adapter->priv->dbus_obj,
357         "handle-switch-user", G_CALLBACK(_handle_switch_user), adapter);
358
359     return adapter;
360 }
361
362 void
363 tlm_dbus_login_adapter_request_completed (
364         TlmDbusRequest *request,
365         GError *error)
366 {
367     g_return_if_fail (request && request->dbus_adapter &&
368             TLM_IS_DBUS_LOGIN_ADAPTER(request->dbus_adapter));
369
370     TlmDbusLoginAdapter *adapter = TLM_DBUS_LOGIN_ADAPTER (
371             request->dbus_adapter);
372     if (error) {
373         g_dbus_method_invocation_return_gerror (request->invocation, error);
374         return;
375     }
376
377     switch (request->type) {
378     case TLM_DBUS_REQUEST_TYPE_LOGIN_USER:
379         tlm_dbus_login_complete_login_user (adapter->priv->dbus_obj,
380                 request->invocation);
381         break;
382     case TLM_DBUS_REQUEST_TYPE_LOGOUT_USER:
383         tlm_dbus_login_complete_logout_user (adapter->priv->dbus_obj,
384                 request->invocation);
385         break;
386     case TLM_DBUS_REQUEST_TYPE_SWITCH_USER:
387         tlm_dbus_login_complete_switch_user (adapter->priv->dbus_obj,
388                 request->invocation);
389         break;
390     }
391 }