@@ -0,0 +1,382 @@
2+ * Copyright 2013 Canonical Ltd.
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
17+ * Alberto Ruiz <alberto.ruiz@canonical.com>
18+ * Renato Araujo Oliveira Filho <renato@canonical.com>
23+#include <glib-object.h>
24+#include <nm-secret-agent.h>
25+#include "secret-agent.h"
27+#define UNITY_SETTINGS_TYPE_SECRET_AGENT (unity_settings_secret_agent_get_type ())
28+#define UNITY_SETTINGS_SECRET_AGENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_SETTINGS_TYPE_SECRET_AGENT, UnitySettingsSecretAgent))
29+#define UNITY_SETTINGS_SECRET_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_SETTINGS_TYPE_SECRET_AGENT, UnitySettingsSecretAgentClass))
30+#define UNITY_SETTINGS_IS_SECRET_AGENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_SETTINGS_TYPE_SECRET_AGENT))
31+#define UNITY_SETTINGS_IS_SECRET_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_SETTINGS_TYPE_SECRET_AGENT))
32+#define UNITY_SETTINGS_SECRET_AGENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_SETTINGS_TYPE_SECRET_AGENT, UnitySettingsSecretAgentClass))
33+#define UNITY_SETTINGS_SECRET_AGENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), UNITY_SETTINGS_TYPE_SECRET_AGENT, UnitySettingsSecretAgentPrivate))
35+#define AGENT_ID "com.canonical.settings.network.nm-agent"
37+static gpointer unity_settings_secret_agent_parent_class = NULL;
39+typedef struct _UnitySettingsSecretAgentPrivate UnitySettingsSecretAgentPrivate;
41+struct _UnitySettingsSecretAgentPrivate {
45+typedef struct _SecretRequest {
47+ NMSecretAgent *agent;
48+ NMConnection *connection;
49+ const char *connection_path;
50+ const char *setting_name;
52+ NMSecretAgentGetSecretsFlags flags;
53+ NMSecretAgentGetSecretsFunc callback;
54+ gpointer callback_data;
57+GType unity_settings_secret_agent_get_type (void) G_GNUC_CONST;
59+ UNITY_SETTINGS_SECRET_AGENT_DUMMY_PROPERTY
68+static guint signals[LAST_SIGNAL] = { 0 };
70+UnitySettingsSecretAgent* unity_settings_secret_agent_new (void);
71+UnitySettingsSecretAgent* unity_settings_secret_agent_construct (GType object_type);
74+secret_request_find (SecretRequest *req,
87+unity_settings_secret_agent_provide_secret (UnitySettingsSecretAgent *agent,
93+ UnitySettingsSecretAgentPrivate *priv = agent->priv;
95+ iter = g_queue_find_custom (priv->requests,
97+ (GCompareFunc)secret_request_find);
99+ if (iter == NULL || iter->data == NULL)
101+ g_warning ("Secret request with id <%d> was not found", (int)request);
107+ req->callback (NM_SECRET_AGENT (agent),
111+ req->callback_data);
113+ g_queue_remove_all (priv->requests, req);
119+free_request (SecretRequest *req)
121+ g_object_unref (req->connection);
126+unity_settings_secret_agent_cancel_request (UnitySettingsSecretAgent *agent,
131+ UnitySettingsSecretAgentPrivate *priv = agent->priv;
134+ iter = g_queue_find_custom (priv->requests,
136+ (GCompareFunc)secret_request_find);
138+ if (iter == NULL || iter->data == NULL)
140+ g_warning ("Secret request with id <%d> was not found", (int)request);
145+ error = g_error_new (NM_SECRET_AGENT_ERROR,
146+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
147+ "This secret request was canceled by the user.");
149+ req->callback (NM_SECRET_AGENT (agent),
153+ req->callback_data);
155+ g_queue_remove_all (priv->requests, req);
161+delete_secrets (NMSecretAgent *agent,
162+ NMConnection *connection,
163+ const char *connection_path,
164+ NMSecretAgentDeleteSecretsFunc callback,
165+ gpointer callback_data)
167+ g_debug ("delete secrets");
170+/* If it returns G_MAXUINT it's considered an error */
172+find_available_id (UnitySettingsSecretAgentPrivate *priv)
175+ guint candidate = 0;
177+ if (g_queue_get_length (priv->requests) == G_MAXUINT)
180+ while (i < g_queue_get_length (priv->requests))
182+ SecretRequest *req = (SecretRequest*)g_queue_peek_nth (priv->requests, i);
184+ if (req->id == candidate)
199+get_secrets (NMSecretAgent *agent,
200+ NMConnection *connection,
201+ const char *connection_path,
202+ const char *setting_name,
204+ NMSecretAgentGetSecretsFlags flags,
205+ NMSecretAgentGetSecretsFunc callback,
206+ gpointer callback_data)
209+ UnitySettingsSecretAgentPrivate *priv = UNITY_SETTINGS_SECRET_AGENT_GET_PRIVATE (agent);
210+ SecretRequest *req = NULL;
212+ if (flags == NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE)
214+ GError *error = g_error_new (NM_SECRET_AGENT_ERROR,
215+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
216+ "No password found for this connection.");
217+ callback (agent, connection, NULL, error, callback_data);
218+ g_error_free (error);
222+ id = find_available_id (priv);
223+ if (id == G_MAXUINT)
225+ GError *error = g_error_new (NM_SECRET_AGENT_ERROR,
226+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
227+ "Reached maximum number of requests.");
228+ callback (agent, connection, NULL, error, callback_data);
229+ g_error_free (error);
233+ /* Adding a request */
234+ req = (SecretRequest*) g_malloc0 (sizeof (SecretRequest));
235+ *req = ((SecretRequest)
246+ g_object_ref (connection);
248+ g_queue_push_tail (priv->requests, req);
250+ g_signal_emit_by_name (agent,
251+ UNITY_SETTINGS_SECRET_AGENT_SECRET_REQUESTED,
260+save_secrets (NMSecretAgent *agent,
261+ NMConnection *connection,
262+ const char *connection_path,
263+ NMSecretAgentSaveSecretsFunc callback,
264+ gpointer callback_data)
266+ g_debug ("save secrets");
270+cancel_get_secrets (NMSecretAgent *agent,
271+ const char *connection_path,
272+ const char *setting_name)
274+ g_debug ("cancel get secrets");
277+UnitySettingsSecretAgent*
278+unity_settings_secret_agent_construct (GType object_type)
280+ UnitySettingsSecretAgent * self = NULL;
281+ self = (UnitySettingsSecretAgent*) g_object_new (object_type,
282+ NM_SECRET_AGENT_IDENTIFIER, AGENT_ID,
288+UnitySettingsSecretAgent*
289+unity_settings_secret_agent_new (void)
291+ return unity_settings_secret_agent_construct (UNITY_SETTINGS_TYPE_SECRET_AGENT);
295+destroy_pending_request (gpointer data)
297+ SecretRequest* req = (SecretRequest*)data;
298+ /* Reporting the cancellation of all pending requests */
299+ g_signal_emit_by_name (req->agent,
300+ UNITY_SETTINGS_SECRET_AGENT_REQUEST_CANCELLED,
307+unity_settings_secret_agent_finalize (GObject *agent)
309+ UnitySettingsSecretAgentPrivate *priv = UNITY_SETTINGS_SECRET_AGENT_GET_PRIVATE (agent);
311+ g_queue_free_full (priv->requests, destroy_pending_request);
315+unity_settings_secret_agent_class_init (UnitySettingsSecretAgentClass *klass)
317+ unity_settings_secret_agent_parent_class = g_type_class_peek_parent (klass);
318+ NMSecretAgentClass *parent_class = NM_SECRET_AGENT_CLASS (klass);
319+ parent_class->get_secrets = get_secrets;
320+ parent_class->save_secrets = save_secrets;
321+ parent_class->delete_secrets = delete_secrets;
322+ parent_class->cancel_get_secrets = cancel_get_secrets;
324+ g_type_class_add_private (klass, sizeof(UnitySettingsSecretAgentPrivate));
325+ G_OBJECT_CLASS (klass)->finalize = unity_settings_secret_agent_finalize;
328+ signals[SECRET_REQUESTED] = g_signal_new (UNITY_SETTINGS_SECRET_AGENT_SECRET_REQUESTED,
329+ G_OBJECT_CLASS_TYPE (G_OBJECT_CLASS (klass)),
331+ G_STRUCT_OFFSET (UnitySettingsSecretAgentClass, secret_requested),
334+ G_TYPE_UINT, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_UINT);
336+ signals[REQUEST_CANCELLED] = g_signal_new (UNITY_SETTINGS_SECRET_AGENT_REQUEST_CANCELLED,
337+ G_OBJECT_CLASS_TYPE (G_OBJECT_CLASS (klass)),
339+ G_STRUCT_OFFSET (UnitySettingsSecretAgentClass, request_cancelled),
347+unity_settings_secret_agent_instance_init (UnitySettingsSecretAgent *self)
349+ self->priv = UNITY_SETTINGS_SECRET_AGENT_GET_PRIVATE (self);
350+ self->priv->requests = g_queue_new ();
354+unity_settings_secret_agent_get_type (void)
356+ static volatile gsize unity_settings_secret_agent_type_id__volatile = 0;
357+ if (g_once_init_enter (&unity_settings_secret_agent_type_id__volatile))
359+ static const GTypeInfo g_define_type_info =
361+ sizeof (UnitySettingsSecretAgentClass),
362+ (GBaseInitFunc) NULL,
363+ (GBaseFinalizeFunc) NULL,
364+ (GClassInitFunc) unity_settings_secret_agent_class_init,
365+ (GClassFinalizeFunc) NULL,
367+ sizeof (UnitySettingsSecretAgent),
369+ (GInstanceInitFunc) unity_settings_secret_agent_instance_init,
372+ GType unity_settings_secret_agent_type_id;
373+ unity_settings_secret_agent_type_id = g_type_register_static (NM_TYPE_SECRET_AGENT,
374+ "UnitySettingsSecretAgent",
375+ &g_define_type_info,
377+ g_once_init_leave (&unity_settings_secret_agent_type_id__volatile,
378+ unity_settings_secret_agent_type_id);
381+ return unity_settings_secret_agent_type_id__volatile;