1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
4 * This file is part of gsignond
6 * Copyright (C) 2013 Intel Corporation.
8 * Contact: Amarnath Valluri <amarnath.valluri@linux.intel.com>
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.
15 * This library is distributed in the hope that it will be useful,
16 * but 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.
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
26 #include "gsignond-signonui-proxy.h"
27 #include <gsignond/gsignond-log.h>
28 #include <gsignond/gsignond-signonui.h>
29 #include "dbus/gsignond-dbus-signonui-adapter.h"
31 static void _process_next_request (GSignondSignonuiProxy *proxy);
32 static void _on_refresh_request (GSignondSignonuiProxy *proxy,
33 gchar *request_id, gpointer userdata);
37 GSignondSignonuiData *ui_data;
38 GSignondSignonuiProxyQueryDialogCb cb;
39 GSignondSignonuiProxyRefreshCb refresh_cb;
44 GSignondSignonuiProxyRefreshDialogCb cb;
49 GSignondSignonuiProxyCancelRequestCb cb;
53 struct _GSignondSignonuiProxyPrivate
55 GSignondDbusSignonuiAdapter *signonui;
56 _UIQueryRequest *active_request; /* Active dialog */
57 GQueue *request_queue; /* request queue */
61 G_DEFINE_TYPE (GSignondSignonuiProxy, gsignond_signonui_proxy, G_TYPE_OBJECT);
62 #define GSIGNOND_SIGNONUI_PROXY_GET_PRIV(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSIGNOND_TYPE_SIGNONUI_PROXY, GSignondSignonuiProxyPrivate)
64 static _UIQueryRequest *
65 _ui_query_request_new (GObject *caller,
66 GSignondSignonuiData *ui_data,
67 GSignondSignonuiProxyQueryDialogCb cb,
68 GSignondSignonuiProxyRefreshCb refresh_cb,
71 _UIQueryRequest *req = g_new0(_UIQueryRequest, 1);
74 req->ui_data = gsignond_signonui_data_ref (ui_data);
76 req->refresh_cb = refresh_cb;
77 req->userdata = userdata;
82 static _UIRefreshRequest *
83 _ui_refresh_request_new (GSignondSignonuiProxyRefreshDialogCb cb, gpointer userdata)
85 _UIRefreshRequest *req = g_new0(_UIRefreshRequest, 1);
88 req->userdata = userdata;
93 static _UICancelRequest *
94 _ui_cancel_request_new (GSignondSignonuiProxyCancelRequestCb cb, gpointer userdata)
96 _UICancelRequest *req = g_new0(_UICancelRequest, 1);
99 req->userdata = userdata;
105 _ui_query_request_free (_UIQueryRequest *req)
108 if (req->ui_data) gsignond_signonui_data_unref (req->ui_data);
113 _dispose (GObject *object)
115 GSignondSignonuiProxy *self = GSIGNOND_SIGNONUI_PROXY (object);
117 if (self->priv->signonui) {
118 g_object_unref (self->priv->signonui);
119 self->priv->signonui = NULL;
122 G_OBJECT_CLASS (gsignond_signonui_proxy_parent_class)->dispose (object);
126 _finalize (GObject *object)
128 GSignondSignonuiProxy *self = GSIGNOND_SIGNONUI_PROXY (object);
130 if (self->priv->request_queue) {
131 g_queue_free_full (self->priv->request_queue, (GDestroyNotify)_ui_query_request_free);
132 self->priv->request_queue = NULL;
135 G_OBJECT_CLASS (gsignond_signonui_proxy_parent_class)->finalize (object);
139 gsignond_signonui_proxy_class_init (GSignondSignonuiProxyClass *klass)
141 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
143 g_type_class_add_private (gobject_class, sizeof (GSignondSignonuiProxyPrivate));
145 gobject_class->dispose = _dispose;
146 gobject_class->finalize = _finalize;
150 gsignond_signonui_proxy_init (GSignondSignonuiProxy *proxy)
152 proxy->priv = GSIGNOND_SIGNONUI_PROXY_GET_PRIV (proxy);
154 proxy->priv->signonui = gsignond_dbus_signonui_adapter_new ();
156 if (proxy->priv->signonui)
157 g_signal_connect_swapped (proxy->priv->signonui, "refresh", G_CALLBACK(_on_refresh_request), proxy);
158 proxy->priv->active_request = NULL;
159 proxy->priv->request_queue = g_queue_new ();
160 proxy->priv->is_idle = TRUE;
164 _on_refresh_request (GSignondSignonuiProxy *proxy, gchar *request_id, gpointer userdata)
166 _UIQueryRequest *req = proxy->priv->active_request;
168 if (req && !g_strcmp0 (G_OBJECT_TYPE_NAME (req->caller), request_id)) {
169 if (req->refresh_cb) req->refresh_cb(req->ui_data, req->userdata);
172 WARN("UI-Error: unhandled refresh request");
177 _query_dialog_cb (GVariant *reply, GError *error, gpointer user_data)
179 GSignondSignonuiProxy *proxy = GSIGNOND_SIGNONUI_PROXY (user_data);
181 _UIQueryRequest *req = proxy->priv->active_request;
184 req->cb (gsignond_signonui_data_new_from_variant (reply), error, req->userdata);
186 WARN ("UI-Error: %s", error->message);
187 g_error_free (error);
190 _ui_query_request_free (req);
192 proxy->priv->active_request = NULL;
194 _process_next_request (proxy);
198 _process_next_request (GSignondSignonuiProxy *proxy)
200 _UIQueryRequest *req = g_queue_pop_head (proxy->priv->request_queue);
203 proxy->priv->is_idle = TRUE;
204 proxy->priv->active_request = NULL;
208 proxy->priv->active_request = req;
210 /* update request id */
211 gsignond_signonui_data_set_request_id (req->ui_data, G_OBJECT_TYPE_NAME(req->caller));
212 gsignond_dbus_signonui_adapter_query_dialog (proxy->priv->signonui,
213 gsignond_signonui_data_to_variant(req->ui_data), _query_dialog_cb, proxy);
215 proxy->priv->is_idle = FALSE;
219 gsignond_signonui_proxy_query_dialog (GSignondSignonuiProxy *proxy,
221 GSignondSignonuiData *ui_data,
222 GSignondSignonuiProxyQueryDialogCb cb,
223 GSignondSignonuiProxyRefreshCb refresh_cb,
227 g_queue_push_tail (proxy->priv->request_queue,
228 _ui_query_request_new (caller, ui_data, cb, refresh_cb, userdata));
230 if (proxy->priv->is_idle) _process_next_request (proxy);
236 _refresh_dialog_cb (GError *error, gpointer user_data)
238 _UIRefreshRequest *req = (_UIRefreshRequest *)user_data;
241 req->cb(error, req->userdata);
243 WARN ("UI-Error : %s", error->message);
244 g_error_free (error);
251 gsignond_signonui_proxy_refresh_dialog (GSignondSignonuiProxy *proxy,
253 GSignondSignonuiData *ui_data,
254 GSignondSignonuiProxyRefreshDialogCb cb,
257 if (proxy->priv->active_request
258 && proxy->priv->active_request->caller == caller) {
259 _UIRefreshRequest *req = _ui_refresh_request_new (cb, userdata);
261 /* FIXME: Is it required to set refresh id for refresh data */
262 gsignond_signonui_data_set_request_id (ui_data, G_OBJECT_TYPE_NAME(caller));
263 gsignond_dbus_signonui_adapter_refresh_dialog (proxy->priv->signonui,
264 gsignond_signonui_data_to_variant (ui_data), _refresh_dialog_cb, req);
273 _cancel_request_cb (GError *error, gpointer user_data)
275 _UICancelRequest *req = (_UICancelRequest*)user_data;
278 req->cb (error, req->userdata);
280 WARN ("UI-Error : %s", error->message);
281 g_error_free (error);
288 _find_request_by_caller (gconstpointer a, gconstpointer b)
290 _UIQueryRequest *req = (_UIQueryRequest *)a;
292 return (req && req->caller == b) ? 0 : 1;
296 gsignond_signonui_proxy_cancel_request (GSignondSignonuiProxy *proxy,
298 GSignondSignonuiProxyCancelRequestCb cb,
301 GList *element = NULL;
302 _UIQueryRequest *req = NULL;
303 /* if no active request to cacel */
304 if (!proxy->priv->active_request) return FALSE;
306 /* cancel active request */
307 if (proxy->priv->active_request->caller == caller) {
308 _UICancelRequest *req = _ui_cancel_request_new (cb, userdata);
309 gsignond_dbus_signonui_adapter_cancel_request (proxy->priv->signonui,
310 G_OBJECT_TYPE_NAME (caller), _cancel_request_cb, req);
314 /* cancel pending request */
315 element = g_queue_find_custom (proxy->priv->request_queue, caller, _find_request_by_caller);
317 if (!element) return FALSE;
321 gsignond_signonui_data_ref (req->ui_data);
322 gsignond_signonui_data_set_query_error(req->ui_data, SIGNONUI_ERROR_CANCELED);
324 req->cb (req->ui_data, NULL, req->userdata);
327 if (cb) cb(NULL, userdata);
332 GSignondSignonuiProxy *
333 gsignond_signonui_proxy_new ()
335 return g_object_new (GSIGNOND_TYPE_SIGNONUI_PROXY, NULL);