74b887bb1ed0373836b41bf6524c9fb367f24f00
[profile/ivi/gsignond.git] / src / daemon / dbus / gsignond-dbus-signonui-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 gsignond
5  *
6  * Copyright (C) 2013 Intel Corporation.
7  *
8  * Contact: Amarnath Valluri <amarnath.valluri@linux.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 "gsignond-dbus-signonui-adapter.h"
27 #include "gsignond/gsignond-log.h"
28 #include "gsignond-dbus.h"
29
30 struct _GSignondDbusSignonuiAdapterPrivate
31 {
32     GDBusConnection *connection;
33     GDBusProxy *proxy;
34     gulong connection_close_signal_id;
35 };
36
37 G_DEFINE_TYPE (GSignondDbusSignonuiAdapter, gsignond_dbus_signonui_adapter, G_TYPE_OBJECT)
38
39 enum {
40     SIG_REFRESH,
41     SIG_MAX
42 };
43
44 static guint _signals[SIG_MAX];
45
46 #define GSIGNOND_DBUS_SIGNONUI_ADAPTER_GET_PRIV(obj) \
47     G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSIGNOND_TYPE_DBUS_SIGNONUI_ADAPTER, GSignondDbusSignonuiAdapterPrivate)
48
49 typedef struct
50 {
51     GSignondDbusSignonuiAdapter *adapter;
52     gpointer cb;
53     gpointer data;
54 } _SignonuiDbusInfo;
55
56 static void
57 _dispose (GObject *object)
58 {
59     GSignondDbusSignonuiAdapter *self = GSIGNOND_DBUS_SIGNONUI_ADAPTER (object);
60
61     if (self->priv->connection_close_signal_id) {
62         g_signal_handler_disconnect (self->priv->connection, self->priv->connection_close_signal_id);
63         self->priv->connection_close_signal_id = 0;
64     }
65
66     if (self->priv->connection) {
67         g_object_unref (self->priv->connection);
68         self->priv->connection = NULL;
69     }
70     
71     if (self->priv->proxy) {
72         g_object_unref (self->priv->proxy);
73         self->priv->proxy = NULL;
74     }
75
76     G_OBJECT_CLASS (gsignond_dbus_signonui_adapter_parent_class)->dispose (object);
77 }
78
79 static void
80 _finalize (GObject *object)
81 {
82     G_OBJECT_CLASS (gsignond_dbus_signonui_adapter_parent_class)->finalize (object);
83 }
84
85 static void
86 gsignond_dbus_signonui_adapter_class_init (GSignondDbusSignonuiAdapterClass *klass)
87 {
88     GObjectClass* object_class = G_OBJECT_CLASS (klass);
89
90     g_type_class_add_private (object_class, sizeof (GSignondDbusSignonuiAdapterPrivate));
91
92     object_class->dispose = _dispose;
93     object_class->finalize = _finalize;
94
95     _signals[SIG_REFRESH] = g_signal_new ("refresh",
96                                           GSIGNOND_TYPE_DBUS_SIGNONUI_ADAPTER,
97                                           G_SIGNAL_RUN_LAST,
98                                           0,
99                                           NULL,
100                                           NULL,
101                                           NULL,
102                                           G_TYPE_NONE,
103                                           1, G_TYPE_STRING);
104 }
105
106 static void
107 gsignond_dbus_signonui_adapter_init (GSignondDbusSignonuiAdapter *self)
108 {
109     self->priv = GSIGNOND_DBUS_SIGNONUI_ADAPTER_GET_PRIV(self);
110     self->priv->connection = 0;
111     self->priv->proxy = 0;
112     self->priv->connection_close_signal_id = 0;
113 }
114
115 static void
116 _on_proxy_signal (GSignondDbusSignonuiAdapter *adapter,
117                   gchar *sender_name,
118                   gchar *signal_name,
119                   GVariant *params,
120                   gpointer user_data)
121 {
122     gchar *request_id = NULL;
123
124     g_return_if_fail (adapter && signal_name && params);
125
126     /* Ignore other than 'refresh' signal */
127     if (g_strcmp0(signal_name, "refresh") != 0) return ;
128
129     if (!g_variant_is_of_type (params, G_VARIANT_TYPE_TUPLE)) {
130         WARN ("Expected 'tuple' type but got '%s' type", 
131                     g_variant_get_type_string (params));
132         return ;
133     }
134
135     g_variant_get (params, "(s)", &request_id);
136
137     if (request_id) {
138         g_signal_emit (adapter, _signals[SIG_REFRESH], 0, request_id);
139         g_free (request_id);
140     }
141 }
142
143 static void
144 _on_connection_closed (GSignondDbusSignonuiAdapter *adapter,
145                        gboolean remote_peer_vanished, 
146                        GError *error,
147                        gpointer user_data)
148 {
149     g_return_if_fail (adapter);
150
151     DBG("UI Connection closed...");
152
153     g_signal_handler_disconnect (adapter->priv->connection, adapter->priv->connection_close_signal_id);
154     adapter->priv->connection_close_signal_id = 0;
155
156     g_clear_object (&adapter->priv->connection);
157     g_clear_object (&adapter->priv->proxy);
158 }
159
160 static gboolean
161 _setup_ui_connection (GSignondDbusSignonuiAdapter *adapter)
162 {
163     GError *err = NULL;
164     GVariant *reply = NULL;
165     gchar *ui_server_address = NULL;
166     GDBusConnection *session_bus = NULL;
167
168     g_return_val_if_fail (adapter, FALSE);
169
170     if (adapter->priv->connection) return TRUE;
171
172     session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &err);
173     if (err) {
174         WARN ("Error getting session bus :%s", err->message);
175         goto fail;
176     }
177
178     reply = g_dbus_connection_call_sync (session_bus, SIGNONUI_SERVICE, SIGNONUI_OBJECTPATH,
179                 SIGNONUI_IFACE, "getBusAddress", g_variant_new ("()"), 
180                 G_VARIANT_TYPE_TUPLE, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
181     if (!reply) {
182         WARN ("Failed to get signon ui bus address : %s", err->message);
183         goto fail;
184     }
185
186     g_variant_get(reply, "(s)", &ui_server_address);
187
188     DBG ("Connecting to UI Server at : %s", ui_server_address);
189
190     adapter->priv->connection = g_dbus_connection_new_for_address_sync (ui_server_address,
191             G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, NULL, NULL, &err);
192     g_free (ui_server_address);
193     if (err) {
194         WARN ("Failed to connect UI server at address '%s' : %s", ui_server_address,
195                 err->message);
196         goto fail;
197     }
198
199     adapter->priv->connection_close_signal_id = 
200             g_signal_connect_swapped (adapter->priv->connection, 
201                 "closed", G_CALLBACK(_on_connection_closed), adapter);
202
203     adapter->priv->proxy = g_dbus_proxy_new_sync (adapter->priv->connection,
204            G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
205            NULL,
206            NULL,
207            SIGNONUI_DIALOG_OBJECTPATH,
208            SIGNONUI_DIALOG_IFACE,
209            NULL,
210            &err);
211     if (err) {
212         WARN ("failed to get ui object : %s", err->message);
213         goto fail;
214     }
215
216     g_signal_connect_swapped (adapter->priv->proxy, "g-signal", G_CALLBACK (_on_proxy_signal), adapter);
217
218     return TRUE;
219 fail:
220     if (err) g_error_free (err);
221     return FALSE;
222 }
223
224 static void
225 _on_query_dialog_ready (GObject *proxy, GAsyncResult *res, gpointer user_data)
226 {
227     GError *error = NULL;
228     GVariant *reply = NULL;
229     _SignonuiDbusInfo *info = (_SignonuiDbusInfo *)user_data;
230
231     reply = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, &error);
232
233     if (info) {
234         if (info->cb) {
235             GVariant *out_params = NULL;
236
237             if (!error) {
238                 g_variant_get (reply, "(@a{sv})", &out_params);
239             }
240             ((GSignondDbusSignonuiQueryDialogCb)info->cb) (out_params, error, info->data);
241             if(out_params) g_variant_unref (out_params);
242         }
243         g_object_unref (info->adapter);
244         g_slice_free (_SignonuiDbusInfo, info);
245     }
246     
247     if (error) g_error_free (error);
248     if (reply) g_variant_unref (reply);
249 }
250
251 gboolean
252 gsignond_dbus_signonui_adapter_query_dialog (GSignondDbusSignonuiAdapter *adapter,
253                                              GVariant *params,
254                                              const GSignondDbusSignonuiQueryDialogCb callback,
255                                              gpointer user_data)
256 {
257     if (!adapter || !GSIGNOND_IS_DBUS_SIGNONUI_ADAPTER (adapter)) {
258         WARN ("assert (!adapter ||!GSIGNOND_IS_DBUS_SIGNONUI_ADAPTER (adapter)) failed"); 
259         return FALSE;
260     }
261     if (!adapter->priv->proxy && !_setup_ui_connection(adapter)) {
262         WARN ("Failed to setup ui connection");
263         return FALSE;
264     }
265     _SignonuiDbusInfo *info = g_slice_new0 (_SignonuiDbusInfo);
266
267     info->adapter = g_object_ref (adapter);
268     info->cb = callback;
269     info->data = user_data;
270
271     g_dbus_proxy_call (adapter->priv->proxy, "queryDialog",
272             g_variant_new ("(@a{sv})", params), G_DBUS_CALL_FLAGS_NONE, G_MAXINT, NULL,
273             _on_query_dialog_ready, (gpointer)info);
274
275     return TRUE;
276 }
277
278 static void
279 _on_refresh_dialog_ready (GObject *proxy, GAsyncResult *res, gpointer user_data)
280 {
281     GError *error = NULL;
282     GVariant *reply = NULL;
283     _SignonuiDbusInfo *info = (_SignonuiDbusInfo *)user_data;
284
285     reply = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, &error);
286
287     if (info) {
288         if (info->cb)
289             ((GSignondDbusSignonuiRefreshDialogCb)info->cb) (error, info->data);
290         g_object_unref (info->adapter);
291         g_slice_free (_SignonuiDbusInfo, info);
292     }
293    
294     if (reply) g_variant_unref (reply);
295     if (error) g_error_free (error);
296 }
297
298 gboolean
299 gsignond_dbus_signonui_adapter_refresh_dialog (GSignondDbusSignonuiAdapter *adapter,
300                                                GVariant *params,
301                                                const GSignondDbusSignonuiRefreshDialogCb callback,
302                                                gpointer user_data)
303 {
304     if (!adapter || !GSIGNOND_IS_DBUS_SIGNONUI_ADAPTER (adapter)) {
305         WARN ("assert (!adapter ||!GSIGNOND_IS_DBUS_SIGNONUI_ADAPTER (adapter)) failed"); 
306         return FALSE;
307     }
308     if (!adapter->priv->proxy && !_setup_ui_connection(adapter)) {
309         WARN ("Failed to setup ui connection");
310         return FALSE;
311     }
312
313     _SignonuiDbusInfo *info = g_slice_new0 (_SignonuiDbusInfo);
314
315     info->adapter = g_object_ref (adapter);
316     info->cb = callback;
317     info->data = user_data;
318
319     g_dbus_proxy_call (adapter->priv->proxy, "refreshDialog",
320             g_variant_new ("(a{sv})", params), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
321             _on_refresh_dialog_ready, (gpointer)info);
322
323     return TRUE;
324 }
325
326 static void
327 _on_cancel_request_ready (GObject *proxy, GAsyncResult *res, gpointer user_data)
328 {
329     GError *error = NULL;
330     GVariant *reply = NULL;
331     _SignonuiDbusInfo *info = (_SignonuiDbusInfo *)user_data;
332
333     reply = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, &error);
334
335     if (info) {
336         if (info->cb)
337             ((GSignondDbusSignonuiCancelRequestCb)info->cb) (error, info->data);
338         g_object_unref (info->adapter);
339         g_slice_free (_SignonuiDbusInfo, info);
340     }
341
342     if (reply) g_variant_unref (reply);
343     if (error) g_error_free (error);
344 }
345
346 gboolean
347 gsignond_dbus_signonui_adapter_cancel_request (GSignondDbusSignonuiAdapter *adapter,
348                                                const gchar *request_id,
349                                                const GSignondDbusSignonuiCancelRequestCb callback,
350                                                gpointer user_data)
351 {
352     if (!adapter || !GSIGNOND_IS_DBUS_SIGNONUI_ADAPTER (adapter)) {
353         WARN ("assert (!adapter ||!GSIGNOND_IS_DBUS_SIGNONUI_ADAPTER (adapter)) failed"); 
354         return FALSE;
355     }
356     if (!adapter->priv->proxy && !_setup_ui_connection(adapter)) {
357         WARN ("Failed to setup ui connection");
358         return FALSE;
359     }
360     _SignonuiDbusInfo *info = g_slice_new0 (_SignonuiDbusInfo);
361
362     info->adapter = g_object_ref (adapter);
363     info->cb = callback;
364     info->data = user_data;
365
366     g_dbus_proxy_call (adapter->priv->proxy, "cancelUiRequest",
367             g_variant_new ("(s)", request_id), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
368             _on_cancel_request_ready, (gpointer)info);
369
370     return TRUE;
371 }
372
373 /**
374  * gsignond_dbus_signonui_adapter_new:
375  *
376  * Creates new instance of #GSignondDbusSignonuiAdapter 
377  *
378  * Retrurns: (transfer full) new instance of #GSignondDbusSignonuiAdapter
379  */
380 GSignondDbusSignonuiAdapter * 
381 gsignond_dbus_signonui_adapter_new ()
382 {
383     GSignondDbusSignonuiAdapter *adapter = GSIGNOND_DBUS_SIGNONUI_ADAPTER (
384         g_object_new (GSIGNOND_TYPE_DBUS_SIGNONUI_ADAPTER, NULL));
385
386     if (!_setup_ui_connection (adapter)) {
387         g_object_unref (adapter);
388         return NULL;
389     }
390
391     return adapter;
392 }