*dbus*gen*
src/daemon/gsignond
test/db/dbtest
-test/passwordplugin/passwordplugintest
+test/plugins/passwordplugintest
+test/plugins/pluginproxytest
stamp-h1
*service
src/daemon/db/Makefile
src/daemon/dbus/Makefile
src/daemon/dbus/services/com.google.code.AccountsSSO.SingleSignOn.service
+src/daemon/plugins/Makefile
src/extensions/Makefile
src/extensions/test/Makefile
src/plugins/Makefile
src/plugins/password/Makefile
test/Makefile
test/db/Makefile
-test/passwordplugin/Makefile
test/daemon/Makefile
test/daemon/services/com.google.code.AccountsSSO.SingleSignOn.service
+test/plugins/Makefile
])
GType gsignond_plugin_get_type (void);
/* Methods */
-void gsignond_plugin_cancel (GSignondPlugin *self);
-void gsignond_plugin_abort (GSignondPlugin *self);
-void gsignond_plugin_process (GSignondPlugin *self,
+void
+gsignond_plugin_cancel (GSignondPlugin *self);
+void
+gsignond_plugin_abort (GSignondPlugin *self);
+void
+gsignond_plugin_process (GSignondPlugin *self,
GSignondSessionData *session_data,
const gchar *mechanism);
-void gsignond_plugin_user_action_finished (GSignondPlugin *self,
+void
+gsignond_plugin_user_action_finished (GSignondPlugin *self,
GSignondSessionData *session_data);
-void gsignond_plugin_refresh (GSignondPlugin *self,
+void
+gsignond_plugin_refresh (GSignondPlugin *self,
GSignondSessionData *session_data);
/* Signals */
-void gsignond_plugin_result (GSignondPlugin *self,
+void
+gsignond_plugin_result (GSignondPlugin *self,
GSignondSessionData *session_data);
-void gsignond_plugin_store (GSignondPlugin *self,
+void
+gsignond_plugin_store (GSignondPlugin *self,
GSignondSessionData *session_data);
-void gsignond_plugin_error (GSignondPlugin *self, GError *error);
-void gsignond_plugin_user_action_required (GSignondPlugin *self,
+void
+gsignond_plugin_error (GSignondPlugin *self, GError *error);
+void
+gsignond_plugin_user_action_required (GSignondPlugin *self,
GSignondSessionData *session_data);
-void gsignond_plugin_refreshed (GSignondPlugin *self,
+void
+gsignond_plugin_refreshed (GSignondPlugin *self,
GSignondSessionData *session_data);
-void gsignond_plugin_status_changed (GSignondPlugin *self,
+void
+gsignond_plugin_status_changed (GSignondPlugin *self,
const gchar *status,
const gchar *message);
gboolean symfound = g_module_symbol (plugin_module,
plugin_get_type, &p);
g_free(plugin_get_type);
- g_module_close (plugin_module);
if (!symfound) {
DBG("Symbol couldn't be resolved");
+ g_module_close (plugin_module);
return NULL;
}
GSignondPlugin* plugin = g_object_new(plugin_get_type_f(), NULL);
if (plugin == NULL) {
DBG("Plugin couldn't be created");
+ g_module_close (plugin_module);
return NULL;
}
-
+ g_module_make_resident (plugin_module);
return plugin;
}
-SUBDIRS = db dbus
+SUBDIRS = db dbus plugins
NULL=
bin_PROGRAMS = gsignond
$(NULL)
gsignond_CFLAGS = \
- -DG_LOG_DOMAIN=\"gsignon-daemon\" \
- -DGSIGNOND_EXTENSIONS_DIR="\"$(libdir)/signon/extensions\"" \
-I$(top_srcdir) \
-I$(top_builddir)/include/ \
-I$(top_builddir)/src/ \
$(top_builddir)/src/common/libgsignond-common.la \
$(top_builddir)/src/daemon/db/libgsignond-db.la \
$(top_builddir)/src/daemon/dbus/libgsignond-dbus.la \
+ $(top_builddir)/src/daemon/plugins/libgsignond-plugins.la \
$(GSIGNOND_LIBS) \
$(NULL)
--- /dev/null
+lib_LTLIBRARIES = libgsignond-plugins.la
+
+libgsignond_plugins_la_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/include \
+ $(GSIGNOND_CFLAGS)
+
+libgsignond_plugins_la_LIBADD = \
+ $(top_srcdir)/src/common/libgsignond-common.la \
+ $(GSIGNOND_LIBS)
+
+libgsignond_plugins_la_SOURCES = \
+ gsignond-plugin-proxy.c \
+ gsignond-plugin-proxy-factory.c
+
+CLEANFILES =
--- /dev/null
+/* vi: set et sw=4 ts=4 cino=t0,(0: */
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of gsignond
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Contact: Alexander Kanavin <alex.kanavin@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include "gsignond-plugin-proxy-factory.h"
+
+G_DEFINE_TYPE (GSignondPluginProxyFactory, gsignond_plugin_proxy_factory, G_TYPE_OBJECT);
+
+
+enum
+{
+ PROP_0,
+
+ PROP_CONFIG,
+
+ N_PROPERTIES
+};
+
+static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
+
+static GObject *
+gsignond_plugin_proxy_factory_constructor (GType gtype,
+ guint n_properties,
+ GObjectConstructParam *properties)
+{
+ GObject *obj;
+
+ {
+ /* Always chain up to the parent constructor */
+ obj = G_OBJECT_CLASS (gsignond_plugin_proxy_factory_parent_class)->constructor (
+ gtype, n_properties, properties);
+ }
+
+ /* update the object state depending on constructor properties */
+ GSignondPluginProxyFactory* self = GSIGNOND_PLUGIN_PROXY_FACTORY(obj);
+
+ return obj;
+}
+
+static void
+gsignond_plugin_proxy_factory_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GSignondPluginProxyFactory *self = GSIGNOND_PLUGIN_PROXY_FACTORY (object);
+ switch (property_id)
+ {
+ case PROP_CONFIG:
+ g_assert (self->config == NULL);
+ self->config = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gsignond_plugin_proxy_factory_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GSignondPluginProxyFactory *self = GSIGNOND_PLUGIN_PROXY_FACTORY (object);
+
+ switch (prop_id)
+ {
+ case PROP_CONFIG:
+ g_value_set_object (value, self->config);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsignond_plugin_proxy_factory_dispose (GObject *gobject)
+{
+ GSignondPluginProxyFactory *self = GSIGNOND_PLUGIN_PROXY_FACTORY (gobject);
+
+ if (self->config) {
+ g_object_unref (self->config);
+ self->config = NULL;
+ }
+
+ /* Chain up to the parent class */
+ G_OBJECT_CLASS (gsignond_plugin_proxy_factory_parent_class)->dispose (gobject);
+}
+
+static void
+gsignond_plugin_proxy_factory_finalize (GObject *gobject)
+{
+ GSignondPluginProxyFactory *self = GSIGNOND_PLUGIN_PROXY_FACTORY (gobject);
+
+ g_hash_table_destroy (self->plugins);
+
+ /* Chain up to the parent class */
+ G_OBJECT_CLASS (gsignond_plugin_proxy_factory_parent_class)->finalize (gobject);
+}
+
+
+static void
+gsignond_plugin_proxy_factory_class_init (GSignondPluginProxyFactoryClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->constructor = gsignond_plugin_proxy_factory_constructor;
+ gobject_class->set_property = gsignond_plugin_proxy_factory_set_property;
+ gobject_class->get_property = gsignond_plugin_proxy_factory_get_property;
+ gobject_class->dispose = gsignond_plugin_proxy_factory_dispose;
+ gobject_class->finalize = gsignond_plugin_proxy_factory_finalize;
+
+ obj_properties[PROP_CONFIG] = g_param_spec_object ("config",
+ "config",
+ "Configuration object",
+ GSIGNOND_TYPE_CONFIG,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS);
+
+
+ g_object_class_install_properties (gobject_class,
+ N_PROPERTIES,
+ obj_properties);
+}
+
+static void
+gsignond_plugin_proxy_factory_init (GSignondPluginProxyFactory *self)
+{
+ self->plugins = g_hash_table_new_full ((GHashFunc)g_str_hash,
+ (GEqualFunc)g_str_equal,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)g_object_unref);
+
+}
+
+GSignondPluginProxyFactory*
+gsignond_plugin_proxy_factory_new(GSignondConfig *config)
+{
+ GSignondPluginProxyFactory* proxy = g_object_new(
+ GSIGNOND_TYPE_PLUGIN_PROXY_FACTORY,
+ "config", config,
+ NULL);
+ return proxy;
+}
+
+GSignondPluginProxy*
+gsignond_plugin_proxy_factory_get_plugin(GSignondPluginProxyFactory* factory,
+ guint32 identity_id,
+ const gchar* plugin_type)
+{
+ g_return_val_if_fail (factory && GSIGNOND_IS_PLUGIN_PROXY_FACTORY(factory), NULL);
+ g_return_val_if_fail (plugin_type, NULL);
+
+ gchar* key = g_strdup_printf("%d %s", identity_id, plugin_type);
+
+ GSignondPluginProxy* proxy = g_hash_table_lookup(factory->plugins, key);
+
+ if (proxy != NULL) {
+ g_free(key);
+ return proxy;
+ }
+ proxy = gsignond_plugin_proxy_new(factory->config, plugin_type);
+ if (proxy == NULL) {
+ g_free(key);
+ return NULL;
+ }
+ g_hash_table_insert(factory->plugins, key, proxy);
+ return proxy;
+
+}
+
+gboolean gsignond_plugin_proxy_factory_add_plugin(
+ GSignondPluginProxyFactory* factory,
+ guint32 identity_id,
+ GSignondPluginProxy* proxy)
+{
+ g_return_val_if_fail (factory && GSIGNOND_IS_PLUGIN_PROXY_FACTORY(factory), FALSE);
+ g_return_val_if_fail (proxy && GSIGNOND_IS_PLUGIN_PROXY(proxy), FALSE);
+
+ gchar* plugin_type;
+ g_object_get (proxy, "type", &plugin_type, NULL);
+ gchar* key = g_strdup_printf("%d %s", identity_id, plugin_type);
+ g_free(plugin_type);
+
+ if (g_hash_table_contains(factory->plugins, key)) {
+ g_free(key);
+ return FALSE;
+ }
+ g_object_ref(proxy);
+ g_hash_table_insert(factory->plugins, key, proxy);
+
+ return TRUE;
+
+
+}
--- /dev/null
+/* vi: set et sw=4 ts=4 cino=t0,(0: */
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of gsignond
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Contact: Alexander Kanavin <alex.kanavin@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __GSIGNOND_PLUGIN_PROXY_FACTORY_H__
+#define __GSIGNOND_PLUGIN_PROXY_FACTORY_H__
+
+#include <glib-object.h>
+#include "gsignond-plugin-proxy.h"
+#include <gsignond/gsignond-config.h>
+
+#define GSIGNOND_TYPE_PLUGIN_PROXY_FACTORY (gsignond_plugin_proxy_factory_get_type ())
+#define GSIGNOND_PLUGIN_PROXY_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSIGNOND_TYPE_PLUGIN_PROXY_FACTORY, GSignondPluginProxyFactory))
+#define GSIGNOND_IS_PLUGIN_PROXY_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSIGNOND_TYPE_PLUGIN_PROXY_FACTORY))
+#define GSIGNOND_PLUGIN_PROXY_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSIGNOND_TYPE_PLUGIN_PROXY_FACTORY, GSignondPluginProxyFactoryClass))
+#define GSIGNOND_IS_PLUGIN_PROXY_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSIGNOND_TYPE_PLUGIN_PROXY_FACTORY))
+#define GSIGNOND_PLUGIN_PROXY_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSIGNOND_TYPE_PLUGIN_PROXY_FACTORY, GSignondPluginProxyFactoryClass))
+
+
+typedef struct _GSignondPluginProxyFactory GSignondPluginProxyFactory;
+typedef struct _GSignondPluginProxyFactoryClass GSignondPluginProxyFactoryClass;
+
+struct _GSignondPluginProxyFactory
+{
+ GObject parent_instance;
+
+ /* Private */
+ GSignondConfig *config;
+ GHashTable* plugins;
+};
+
+struct _GSignondPluginProxyFactoryClass
+{
+ GObjectClass parent_class;
+};
+
+GType gsignond_plugin_proxy_factory_get_type (void);
+
+GSignondPluginProxyFactory*
+gsignond_plugin_proxy_factory_new(GSignondConfig *config);
+
+GSignondPluginProxy*
+gsignond_plugin_proxy_factory_get_plugin(GSignondPluginProxyFactory* factory,
+ guint32 identity_id,
+ const gchar* plugin_type);
+
+gboolean gsignond_plugin_proxy_factory_add_plugin(
+ GSignondPluginProxyFactory* factory,
+ guint32 identity_id,
+ GSignondPluginProxy* proxy);
+
+#endif /* __GSIGNOND_PLUGIN_PROXY_FACTORY_H__ */
\ No newline at end of file
--- /dev/null
+/* vi: set et sw=4 ts=4 cino=t0,(0: */
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of gsignond
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Contact: Alexander Kanavin <alex.kanavin@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include "gsignond-plugin-proxy.h"
+#include <gsignond/gsignond-plugin-loader.h>
+#include <gsignond/gsignond-error.h>
+#include <gsignond/gsignond-log.h>
+
+typedef struct {
+ GSignondAuthSessionIface* auth_session;
+ GSignondSessionData* session_data;
+ gchar* mechanism;
+} GSignondProcessData;
+
+static GSignondProcessData*
+gsignond_process_data_new(GSignondAuthSessionIface* auth_session,
+ GSignondSessionData* session_data,
+ const gchar* mechanism)
+{
+ GSignondProcessData* data = g_new0(GSignondProcessData, 1);
+ g_object_ref(auth_session);
+ data->auth_session = auth_session;
+ data->session_data = gsignond_dictionary_copy(session_data);
+ data->mechanism = g_strdup(mechanism);
+ return data;
+}
+
+static void gsignond_process_data_free(GSignondProcessData* data)
+{
+ g_object_unref(data->auth_session);
+ gsignond_dictionary_free(data->session_data);
+ g_free(data->mechanism);
+ g_free(data);
+}
+
+
+G_DEFINE_TYPE (GSignondPluginProxy, gsignond_plugin_proxy, G_TYPE_OBJECT);
+
+
+enum
+{
+ PROP_0,
+
+ PROP_TYPE,
+ PROP_MECHANISMS,
+ PROP_CONFIG,
+
+ N_PROPERTIES
+};
+
+static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
+
+static void gsignond_plugin_proxy_result_callback(GSignondPlugin* plugin,
+ GSignondSessionData* result,
+ gpointer user_data);
+static void gsignond_plugin_proxy_store_callback(GSignondPlugin* plugin,
+ GSignondSessionData* result,
+ gpointer user_data);
+static void gsignond_plugin_proxy_refreshed_callback(GSignondPlugin* plugin,
+ GSignondSessionData* result,
+ gpointer user_data);
+static void gsignond_plugin_proxy_user_action_required_callback(
+ GSignondPlugin* plugin,
+ GSignondSessionData* ui_request,
+ gpointer user_data);
+static void gsignond_plugin_proxy_error_callback(GSignondPlugin* plugin,
+ GError* error,
+ gpointer user_data);
+static void gsignond_plugin_proxy_status_changed_callback(GSignondPlugin* plugin,
+ const gchar* status,
+ const gchar* message,
+ gpointer user_data);
+
+static GObject *
+gsignond_plugin_proxy_constructor (GType gtype,
+ guint n_properties,
+ GObjectConstructParam *properties)
+{
+ GObject *obj;
+
+ {
+ /* Always chain up to the parent constructor */
+ obj = G_OBJECT_CLASS (gsignond_plugin_proxy_parent_class)->constructor (
+ gtype, n_properties, properties);
+ }
+
+ /* update the object state depending on constructor properties */
+ GSignondPluginProxy* self = GSIGNOND_PLUGIN_PROXY(obj);
+ self->plugin = gsignond_load_plugin(self->config, self->plugin_type);
+
+ if (self->plugin != NULL) {
+ g_signal_connect(self->plugin, "result", G_CALLBACK(
+ gsignond_plugin_proxy_result_callback), self);
+ g_signal_connect(self->plugin, "user-action-required", G_CALLBACK(
+ gsignond_plugin_proxy_user_action_required_callback), self);
+ g_signal_connect(self->plugin, "error", G_CALLBACK(
+ gsignond_plugin_proxy_error_callback), self);
+ g_signal_connect(self->plugin, "store", G_CALLBACK(
+ gsignond_plugin_proxy_store_callback), self);
+ g_signal_connect(self->plugin, "refreshed", G_CALLBACK(
+ gsignond_plugin_proxy_refreshed_callback), self);
+ g_signal_connect(self->plugin, "status-changed", G_CALLBACK(
+ gsignond_plugin_proxy_status_changed_callback), self);
+ }
+ return obj;
+}
+
+static void
+gsignond_plugin_proxy_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (object);
+ switch (property_id)
+ {
+ case PROP_TYPE:
+ g_free (self->plugin_type);
+ self->plugin_type = g_value_dup_string (value);
+ break;
+ case PROP_CONFIG:
+ g_assert (self->config == NULL);
+ self->config = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gsignond_plugin_proxy_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (object);
+
+ switch (prop_id)
+ {
+ case PROP_TYPE:
+ g_value_set_string (value, self->plugin_type);
+ break;
+ case PROP_MECHANISMS:
+ g_object_get_property(G_OBJECT(self->plugin), "mechanisms", value);
+ break;
+ case PROP_CONFIG:
+ g_value_set_object (value, self->config);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsignond_plugin_proxy_dispose (GObject *gobject)
+{
+ GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (gobject);
+
+ if (self->plugin) {
+ g_object_unref (self->plugin);
+ self->plugin = NULL;
+ }
+ if (self->config) {
+ g_object_unref (self->config);
+ self->config = NULL;
+ }
+ if (self->active_session) {
+ g_object_unref (self->active_session);
+ self->active_session = NULL;
+ }
+
+ /* Chain up to the parent class */
+ G_OBJECT_CLASS (gsignond_plugin_proxy_parent_class)->dispose (gobject);
+}
+
+static void
+gsignond_plugin_proxy_finalize (GObject *gobject)
+{
+ GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (gobject);
+
+ g_free (self->plugin_type);
+ g_queue_free_full(self->session_queue, (GDestroyNotify)gsignond_process_data_free);
+
+ /* Chain up to the parent class */
+ G_OBJECT_CLASS (gsignond_plugin_proxy_parent_class)->finalize (gobject);
+}
+
+
+static void
+gsignond_plugin_proxy_class_init (GSignondPluginProxyClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->constructor = gsignond_plugin_proxy_constructor;
+ gobject_class->set_property = gsignond_plugin_proxy_set_property;
+ gobject_class->get_property = gsignond_plugin_proxy_get_property;
+ gobject_class->dispose = gsignond_plugin_proxy_dispose;
+ gobject_class->finalize = gsignond_plugin_proxy_finalize;
+
+ obj_properties[PROP_TYPE] =
+ g_param_spec_string ("type",
+ "Plugin type",
+ "Set the plugin type for the proxy",
+ "" /* default value */,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE
+ | G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_MECHANISMS] = g_param_spec_boxed ("mechanisms",
+ "Mechanisms",
+ "List of plugin mechanisms",
+ G_TYPE_STRV, G_PARAM_READABLE);
+
+
+ obj_properties[PROP_CONFIG] = g_param_spec_object ("config",
+ "config",
+ "Configuration object",
+ GSIGNOND_TYPE_CONFIG,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS);
+
+
+ g_object_class_install_properties (gobject_class,
+ N_PROPERTIES,
+ obj_properties);
+}
+
+static void
+gsignond_plugin_proxy_init (GSignondPluginProxy *self)
+{
+ self->session_queue = g_queue_new();
+ self->active_session = NULL;
+
+}
+
+GSignondPluginProxy*
+gsignond_plugin_proxy_new(GSignondConfig *config, const gchar* plugin_type)
+{
+ GSignondPluginProxy* proxy = g_object_new(GSIGNOND_TYPE_PLUGIN_PROXY,
+ "config", config,
+ "type", plugin_type,
+ NULL);
+ if (proxy->plugin != NULL) {
+ gchar *type;
+ g_object_get(proxy->plugin, "type", &type);
+ if (g_strcmp0(type, plugin_type) == 0) {
+ g_free(type);
+ return proxy;
+ }
+ g_free(type);
+ }
+ g_object_unref(proxy);
+ return NULL;
+}
+
+static
+gsignond_plugin_proxy_process_queue(GSignondPluginProxy *self)
+{
+ GSignondProcessData* next_data = g_queue_pop_head(self->session_queue);
+ if (next_data) {
+ self->active_session = next_data->auth_session;
+ g_object_ref(self->active_session);
+ gsignond_plugin_process(self->plugin, next_data->session_data,
+ next_data->mechanism);
+ gsignond_process_data_free(next_data);
+ }
+}
+
+void gsignond_plugin_proxy_process (GSignondPluginProxy *self,
+ GSignondAuthSessionIface* session,
+ GSignondSessionData *session_data,
+ const gchar *mechanism)
+{
+ g_queue_push_tail(self->session_queue, gsignond_process_data_new(session,
+ session_data,
+ mechanism));
+ if (self->active_session == NULL) {
+ gsignond_plugin_proxy_process_queue(self);
+ }
+}
+
+static gint
+gsignond_plugin_proxy_compare_process_data (gconstpointer process_data,
+ gconstpointer auth_session)
+{
+ if (auth_session == ((GSignondProcessData*)process_data)->auth_session)
+ return 0;
+ else
+ return 1;
+}
+
+static GSignondProcessData*
+gsignond_plugin_proxy_find_by_session_iface(GSignondPluginProxy *self,
+ GSignondAuthSessionIface* session)
+{
+ return (GSignondProcessData*)g_queue_find_custom(self->session_queue,
+ session,
+ gsignond_plugin_proxy_compare_process_data);
+}
+
+void
+gsignond_plugin_proxy_cancel (GSignondPluginProxy *self,
+ GSignondAuthSessionIface* session)
+{
+ if (session == self->active_session) {
+ gsignond_plugin_cancel(self->plugin);
+ g_object_unref(self->active_session);
+ self->active_session = NULL;
+ gsignond_plugin_proxy_process_queue(self);
+ } else {
+ GSignondProcessData* data = gsignond_plugin_proxy_find_by_session_iface(
+ self, session);
+ if (data == NULL) {
+ GError* error = g_error_new(GSIGNOND_ERROR,
+ GSIGNOND_ERROR_WRONG_STATE,
+ "Canceling an unknown session");
+ gsignond_auth_session_iface_notify_process_error(session, error);
+ g_error_free(error);
+ return;
+ }
+ g_queue_remove(self->session_queue, data);
+ }
+}
+
+void gsignond_plugin_proxy_user_action_finished (GSignondPluginProxy *self,
+ GSignondSessionData *session_data)
+{
+ if (self->active_session == NULL) {
+ ERR("Error: 'user_action_finished' requested for plugin %s but no \
+ active session", self->plugin_type);
+ return;
+ }
+ gsignond_plugin_user_action_finished(self->plugin, session_data);
+}
+
+void gsignond_plugin_proxy_refresh (GSignondPluginProxy *self,
+ GSignondSessionData *session_data)
+{
+ if (self->active_session == NULL) {
+ ERR("Error: 'refresh' requested for plugin %s but no active session",
+ self->plugin_type);
+ return;
+ }
+ gsignond_plugin_refresh(self->plugin, session_data);
+}
+
+static void gsignond_plugin_proxy_result_callback(GSignondPlugin* plugin,
+ GSignondSessionData* result,
+ gpointer user_data)
+{
+ GSignondPluginProxy* self = GSIGNOND_PLUGIN_PROXY(user_data);
+ if (self->active_session == NULL) {
+ ERR("Error: plugin %s reported 'result', but no active session \
+ in plugin proxy", self->plugin_type);
+ return;
+ }
+ // This avoids problems if cancel() is called from AuthSession handler
+ GSignondAuthSessionIface* active_session = self->active_session;
+ self->active_session = NULL;
+ gsignond_auth_session_iface_notify_process_result(active_session, result);
+ g_object_unref(active_session);
+ gsignond_plugin_proxy_process_queue(self);
+}
+
+static void gsignond_plugin_proxy_store_callback(GSignondPlugin* plugin,
+ GSignondSessionData* result,
+ gpointer user_data)
+{
+ GSignondPluginProxy* self = GSIGNOND_PLUGIN_PROXY(user_data);
+ if (self->active_session == NULL) {
+ ERR("Error: plugin %s reported 'store', but no active session \
+ in plugin proxy", self->plugin_type);
+ return;
+ }
+ gsignond_auth_session_iface_notify_store(self->active_session, result);
+}
+
+static void gsignond_plugin_proxy_refreshed_callback(GSignondPlugin* plugin,
+ GSignondSessionData* result,
+ gpointer user_data)
+{
+ GSignondPluginProxy* self = GSIGNOND_PLUGIN_PROXY(user_data);
+ if (self->active_session == NULL) {
+ ERR("Error: plugin %s reported 'refreshed', but no active session \
+ in plugin proxy", self->plugin_type);
+ return;
+ }
+ gsignond_auth_session_iface_notify_refreshed(self->active_session, result);
+}
+
+static void gsignond_plugin_proxy_user_action_required_callback(
+ GSignondPlugin* plugin,
+ GSignondSessionData* ui_request,
+ gpointer user_data)
+{
+ GSignondPluginProxy* self = GSIGNOND_PLUGIN_PROXY(user_data);
+ if (self->active_session == NULL) {
+ ERR("Error: plugin %s reported 'user_action_required', but no active session \
+ in plugin proxy", self->plugin_type);
+ return;
+ }
+ gsignond_auth_session_iface_notify_user_action_required(
+ self->active_session, ui_request);
+}
+
+static void gsignond_plugin_proxy_error_callback(GSignondPlugin* plugin,
+ GError* error,
+ gpointer user_data)
+{
+ GSignondPluginProxy* self = GSIGNOND_PLUGIN_PROXY(user_data);
+ if (self->active_session == NULL) {
+ ERR("Error: plugin %s reported error %s, but no active session \
+ in plugin proxy", self->plugin_type, error->message);
+ return;
+ }
+ // This avoids problems if cancel() is called from AuthSession handler
+ GSignondAuthSessionIface* active_session = self->active_session;
+ self->active_session = NULL;
+ gsignond_auth_session_iface_notify_process_error(active_session, error);
+ g_object_unref(active_session);
+ gsignond_plugin_proxy_process_queue(self);
+}
+
+static void gsignond_plugin_proxy_status_changed_callback(GSignondPlugin* plugin,
+ const gchar* status,
+ const gchar* message,
+ gpointer user_data)
+{
+ GSignondPluginProxy* self = GSIGNOND_PLUGIN_PROXY(user_data);
+ if (self->active_session == NULL) {
+ ERR("Error: plugin %s reported change in status %s with message %s, \
+ but no active session in plugin proxy", self->plugin_type, status,
+ message);
+ return;
+ }
+ gsignond_auth_session_iface_notify_status_changed(self->active_session,
+ status, message);
+}
--- /dev/null
+/* vi: set et sw=4 ts=4 cino=t0,(0: */
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of gsignond
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Contact: Alexander Kanavin <alex.kanavin@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __GSIGNOND_PLUGIN_PROXY_H__
+#define __GSIGNOND_PLUGIN_PROXY_H__
+
+#include <glib-object.h>
+#include <gsignond/gsignond-plugin-interface.h>
+#include <gsignond/gsignond-config.h>
+#include "../gsignond-auth-session-iface.h"
+
+#define GSIGNOND_TYPE_PLUGIN_PROXY (gsignond_plugin_proxy_get_type ())
+#define GSIGNOND_PLUGIN_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSIGNOND_TYPE_PLUGIN_PROXY, GSignondPluginProxy))
+#define GSIGNOND_IS_PLUGIN_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSIGNOND_TYPE_PLUGIN_PROXY))
+#define GSIGNOND_PLUGIN_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSIGNOND_TYPE_PLUGIN_PROXY, GSignondPluginProxyClass))
+#define GSIGNOND_IS_PLUGIN_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSIGNOND_TYPE_PLUGIN_PROXY))
+#define GSIGNOND_PLUGIN_PROXY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSIGNOND_TYPE_PLUGIN_PROXY, GSignondPluginProxyClass))
+
+
+typedef struct _GSignondPluginProxy GSignondPluginProxy;
+typedef struct _GSignondPluginProxyClass GSignondPluginProxyClass;
+
+struct _GSignondPluginProxy
+{
+ GObject parent_instance;
+
+ /* Private */
+ GSignondConfig *config;
+ gchar* plugin_type;
+ GSignondPlugin* plugin;
+ GQueue* session_queue;
+ GSignondAuthSessionIface* active_session;
+};
+
+struct _GSignondPluginProxyClass
+{
+ GObjectClass parent_class;
+};
+
+GType gsignond_plugin_proxy_get_type (void);
+
+GSignondPluginProxy*
+gsignond_plugin_proxy_new(GSignondConfig *config, const gchar* plugin_type);
+
+
+void
+gsignond_plugin_proxy_cancel (GSignondPluginProxy *self,
+ GSignondAuthSessionIface* session);
+void gsignond_plugin_proxy_process (GSignondPluginProxy *self,
+ GSignondAuthSessionIface* session,
+ GSignondSessionData *session_data,
+ const gchar *mechanism);
+void gsignond_plugin_proxy_user_action_finished (GSignondPluginProxy *self,
+ GSignondSessionData *session_data);
+void gsignond_plugin_proxy_refresh (GSignondPluginProxy *self,
+ GSignondSessionData *session_data);
+
+
+#endif /* __GSIGNOND_PLUGIN_PROXY_H__ */
\ No newline at end of file
-SUBDIRS = db passwordplugin daemon
+SUBDIRS = db plugins daemon
+++ /dev/null
-TESTS = passwordplugintest
-TESTS_ENVIRONMENT= SSO_PLUGINS_DIR=$(top_builddir)/src/plugins/password/.libs
-
-check_PROGRAMS = passwordplugintest
-passwordplugintest_SOURCES = passwordplugintest.c
-passwordplugintest_CFLAGS = \
- $(GSIGNOND_CFLAGS) \
- $(CHECK_CFLAGS) \
- -I$(top_srcdir)/src/plugins/password \
- -I$(top_srcdir)/include/
-
-passwordplugintest_LDADD = \
- $(top_builddir)/src/common/libgsignond-common.la \
- $(top_builddir)/src/plugins/password/libpassword.la \
- $(GSIGNOND_LIBS) \
- $(CHECK_LIBS)
--- /dev/null
+TESTS = passwordplugintest pluginproxytest
+TESTS_ENVIRONMENT= SSO_PLUGINS_DIR=$(top_builddir)/src/plugins/password/.libs
+
+check_PROGRAMS = passwordplugintest pluginproxytest
+passwordplugintest_SOURCES = passwordplugintest.c
+passwordplugintest_CFLAGS = \
+ $(GSIGNOND_CFLAGS) \
+ $(CHECK_CFLAGS) \
+ -I$(top_srcdir)/src/plugins/password \
+ -I$(top_srcdir)/include/
+
+passwordplugintest_LDADD = \
+ $(top_builddir)/src/common/libgsignond-common.la \
+ $(top_builddir)/src/plugins/password/libpassword.la \
+ $(GSIGNOND_LIBS) \
+ $(CHECK_LIBS)
+
+pluginproxytest_SOURCES = pluginproxytest.c
+pluginproxytest_CFLAGS = \
+ $(GSIGNOND_CFLAGS) \
+ $(CHECK_CFLAGS) \
+ -I$(top_srcdir)/src/daemon/plugins \
+ -I$(top_srcdir)/include/
+
+pluginproxytest_LDADD = \
+ $(top_builddir)/src/common/libgsignond-common.la \
+ $(top_builddir)/src/daemon/plugins/libgsignond-plugins.la \
+ $(GSIGNOND_LIBS) \
+ $(CHECK_LIBS)
+
\ No newline at end of file
}
END_TEST
-START_TEST (test_passwordplugin_loader)
-{
- GSignondConfig* config = gsignond_config_new();
- fail_if(config == NULL);
-
- GSignondPlugin* absent_plugin = gsignond_load_plugin(config, "absentplugin");
- fail_if(absent_plugin != NULL);
-
- GSignondPlugin* plugin = gsignond_load_plugin(config, "password");
- check_plugin(plugin);
-
- g_object_unref(plugin);
- g_object_unref(config);
-}
-END_TEST
-
Suite* passwordplugin_suite (void)
{
Suite *s = suite_create ("Password plugin");
tcase_add_test (tc_core, test_passwordplugin_process);
tcase_add_test (tc_core, test_passwordplugin_user_action_finished);
tcase_add_test (tc_core, test_passwordplugin_refresh);
- tcase_add_test (tc_core, test_passwordplugin_loader);
suite_add_tcase (s, tc_core);
return s;
}
--- /dev/null
+/* vi: set et sw=4 ts=4 cino=t0,(0: */
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of gsignond
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Contact: Alexander Kanavin <alex.kanavin@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <check.h>
+#include <stdlib.h>
+#include <glib-object.h>
+#include "gsignond-plugin-proxy.h"
+#include "gsignond-plugin-proxy-factory.h"
+#include <gsignond/gsignond-plugin-loader.h>
+#include <gsignond/gsignond-error.h>
+
+
+static void check_plugin(GSignondPlugin* plugin)
+{
+ gchar* type;
+ gchar** mechanisms;
+
+ fail_if(plugin == NULL);
+
+ g_object_get(plugin, "type", &type, "mechanisms", &mechanisms, NULL);
+
+ fail_unless(g_strcmp0(type, "password") == 0);
+ fail_unless(g_strcmp0(mechanisms[0], "password") == 0);
+ fail_unless(mechanisms[1] == NULL);
+
+ g_free(type);
+ g_strfreev(mechanisms);
+}
+
+
+
+START_TEST (test_plugin_loader)
+{
+ GSignondConfig* config = gsignond_config_new();
+ fail_if(config == NULL);
+
+ GSignondPlugin* absent_plugin = gsignond_load_plugin(config, "absentplugin");
+ fail_if(absent_plugin != NULL);
+
+ GSignondPlugin* plugin = gsignond_load_plugin(config, "password");
+ check_plugin(plugin);
+
+ g_object_unref(plugin);
+ g_object_unref(config);
+}
+END_TEST
+
+static void check_plugin_proxy(GSignondPluginProxy* proxy)
+{
+ gchar* type;
+ gchar** mechanisms;
+
+ fail_if(proxy == NULL);
+
+ g_object_get(proxy, "type", &type, "mechanisms", &mechanisms, NULL);
+
+ fail_unless(g_strcmp0(type, "password") == 0);
+ fail_unless(g_strcmp0(mechanisms[0], "password") == 0);
+ fail_unless(mechanisms[1] == NULL);
+
+ g_free(type);
+ g_strfreev(mechanisms);
+}
+
+START_TEST (test_pluginproxy_create)
+{
+ GSignondConfig* config = gsignond_config_new();
+ fail_if(config == NULL);
+
+ GSignondPluginProxy* proxy = gsignond_plugin_proxy_new(config, "password");
+ fail_if (proxy == NULL);
+ check_plugin_proxy(proxy);
+
+ GSignondPluginProxy* proxy2 = gsignond_plugin_proxy_new(config, "absentplugin");
+ fail_if (proxy2 != NULL);
+
+ g_object_unref(proxy);
+ g_object_unref(config);
+}
+END_TEST
+
+gboolean testing_proxy_process = FALSE;
+gboolean testing_proxy_process_cancel = FALSE;
+gboolean testing_proxy_process_queue = FALSE;
+gint proxy_process_queue_results = 0;
+gboolean testing_proxy_process_queue_cancel = FALSE;
+gint proxy_process_queue_cancel_results = 0;
+
+void
+gsignond_auth_session_iface_notify_process_result (
+ GSignondAuthSessionIface *iface,
+ GSignondSessionData *result)
+{
+ int i;
+
+ if (testing_proxy_process) {
+ testing_proxy_process = FALSE;
+ fail_if(g_strcmp0(
+ gsignond_session_data_get_username(result), "megauser") != 0);
+ fail_if(g_strcmp0(
+ gsignond_session_data_get_secret(result), "megapassword") != 0);
+ } else if (testing_proxy_process_cancel) {
+ GSignondPluginProxy* proxy = GSIGNOND_PLUGIN_PROXY(iface); //hackish
+ gsignond_plugin_proxy_cancel(proxy, iface);
+ } else if (testing_proxy_process_queue) {
+ proxy_process_queue_results++;
+ if (proxy_process_queue_results == 1) {
+ GSignondPluginProxy* proxy = GSIGNOND_PLUGIN_PROXY(iface); //hackish
+ GSignondSessionData* data = gsignond_dictionary_new();
+ fail_if(data == NULL);
+ gsignond_session_data_set_username(data, "megauser");
+ gsignond_session_data_set_secret(data, "megapassword");
+
+ gsignond_plugin_proxy_process(proxy, iface, data, "password");
+ gsignond_plugin_proxy_process(proxy, iface, data, "password");
+
+ gsignond_dictionary_free(data);
+ }
+ if (proxy_process_queue_results == 3) {
+ testing_proxy_process_queue = FALSE;
+ }
+ } else if (testing_proxy_process_queue_cancel) {
+ proxy_process_queue_cancel_results++;
+ if (proxy_process_queue_cancel_results == 1) {
+ GSignondPluginProxy* proxy = GSIGNOND_PLUGIN_PROXY(iface); //hackish
+ GSignondSessionData* data = gsignond_dictionary_new();
+ fail_if(data == NULL);
+ gsignond_session_data_set_username(data, "megauser");
+ gsignond_session_data_set_secret(data, "megapassword");
+
+ for (i = 0; i < 9; i++)
+ gsignond_plugin_proxy_process(proxy, iface, data, "password");
+
+ gsignond_dictionary_free(data);
+ }
+ if (proxy_process_queue_cancel_results == 5) {
+ GSignondPluginProxy* proxy = GSIGNOND_PLUGIN_PROXY(iface); //hackish
+ gsignond_plugin_proxy_cancel(proxy, iface);
+ }
+ if (proxy_process_queue_cancel_results == 10) {
+ testing_proxy_process_queue_cancel = FALSE;
+ }
+ } else
+ fail_if(TRUE);
+}
+
+void
+gsignond_auth_session_iface_notify_process_error (
+ GSignondAuthSessionIface *iface,
+ const GError *error)
+{
+ if (testing_proxy_process_cancel) {
+ fail_if(error->code != GSIGNOND_ERROR_WRONG_STATE);
+ testing_proxy_process_cancel = FALSE;
+ } else if (testing_proxy_process_queue_cancel) {
+ fail_if(error->code != GSIGNOND_ERROR_WRONG_STATE);
+ } else
+ fail_if(TRUE);
+}
+
+void
+gsignond_auth_session_iface_notify_store (GSignondAuthSessionIface *self,
+ GSignondSessionData *session_data)
+{
+ fail_if(TRUE);
+}
+
+void
+gsignond_auth_session_iface_notify_user_action_required (GSignondAuthSessionIface *self,
+ GSignondSessionData *session_data)
+{
+ fail_if(TRUE);
+}
+
+void
+gsignond_auth_session_iface_notify_refreshed (GSignondAuthSessionIface *self,
+ GSignondSessionData *session_data)
+{
+ fail_if(TRUE);
+}
+
+void
+gsignond_auth_session_iface_notify_status_changed (GSignondAuthSessionIface *self,
+ const gchar *status,
+ const gchar *message)
+{
+ fail_if(TRUE);
+}
+
+START_TEST (test_pluginproxy_process)
+{
+ GSignondConfig* config = gsignond_config_new();
+ fail_if(config == NULL);
+
+ GSignondPluginProxy* proxy = gsignond_plugin_proxy_new(config, "password");
+ fail_if (proxy == NULL);
+
+ GSignondSessionData* data = gsignond_dictionary_new();
+ fail_if(data == NULL);
+ gsignond_session_data_set_username(data, "megauser");
+ gsignond_session_data_set_secret(data, "megapassword");
+
+ gpointer obj = g_object_new(G_TYPE_OBJECT, NULL);
+
+ testing_proxy_process = TRUE;
+ gsignond_plugin_proxy_process(proxy, obj, data, "password");
+
+ gsignond_dictionary_free(data);
+ g_object_unref(obj);
+ g_object_unref(proxy);
+ g_object_unref(config);
+}
+END_TEST
+
+START_TEST (test_pluginproxy_process_cancel)
+{
+ GSignondConfig* config = gsignond_config_new();
+ fail_if(config == NULL);
+
+ GSignondPluginProxy* proxy = gsignond_plugin_proxy_new(config, "password");
+ fail_if (proxy == NULL);
+
+ GSignondSessionData* data = gsignond_dictionary_new();
+ fail_if(data == NULL);
+ gsignond_session_data_set_username(data, "megauser");
+ gsignond_session_data_set_secret(data, "megapassword");
+
+ testing_proxy_process_cancel = TRUE;
+ gsignond_plugin_proxy_process(proxy, (GSignondAuthSessionIface*)proxy, data, "password");
+ fail_if(testing_proxy_process_cancel);
+
+ gsignond_dictionary_free(data);
+ g_object_unref(proxy);
+ g_object_unref(config);
+}
+END_TEST
+
+START_TEST (test_pluginproxy_process_queue)
+{
+ GSignondConfig* config = gsignond_config_new();
+ fail_if(config == NULL);
+
+ GSignondPluginProxy* proxy = gsignond_plugin_proxy_new(config, "password");
+ fail_if (proxy == NULL);
+
+ GSignondSessionData* data = gsignond_dictionary_new();
+ fail_if(data == NULL);
+ gsignond_session_data_set_username(data, "megauser");
+ gsignond_session_data_set_secret(data, "megapassword");
+
+ testing_proxy_process_queue = TRUE;
+ gsignond_plugin_proxy_process(proxy, (GSignondAuthSessionIface*)proxy, data, "password");
+ fail_if(testing_proxy_process_queue);
+ fail_if(proxy_process_queue_results < 3);
+
+ gsignond_dictionary_free(data);
+ g_object_unref(proxy);
+ g_object_unref(config);
+}
+END_TEST
+
+START_TEST (test_pluginproxy_process_queue_cancel)
+{
+ GSignondConfig* config = gsignond_config_new();
+ fail_if(config == NULL);
+
+ GSignondPluginProxy* proxy = gsignond_plugin_proxy_new(config, "password");
+ fail_if (proxy == NULL);
+
+ GSignondSessionData* data = gsignond_dictionary_new();
+ fail_if(data == NULL);
+ gsignond_session_data_set_username(data, "megauser");
+ gsignond_session_data_set_secret(data, "megapassword");
+
+ testing_proxy_process_queue_cancel = TRUE;
+ gsignond_plugin_proxy_process(proxy, (GSignondAuthSessionIface*)proxy, data, "password");
+ fail_if(testing_proxy_process_queue_cancel);
+ fail_if(proxy_process_queue_cancel_results != 10);
+
+ gsignond_dictionary_free(data);
+ g_object_unref(proxy);
+ g_object_unref(config);
+}
+END_TEST
+
+START_TEST (test_pluginproxyfactory_get)
+{
+ GSignondConfig* config = gsignond_config_new();
+ fail_if(config == NULL);
+
+ GSignondPluginProxyFactory* factory = gsignond_plugin_proxy_factory_new(config);
+ fail_if(factory == NULL);
+
+ fail_if(gsignond_plugin_proxy_factory_get_plugin(factory, 123, "absentplugin") != NULL);
+
+ GSignondPluginProxy* proxy1 = gsignond_plugin_proxy_factory_get_plugin(
+ factory, 123, "password");
+ GSignondPluginProxy* proxy2 = gsignond_plugin_proxy_factory_get_plugin(
+ factory, 456, "password");
+ GSignondPluginProxy* proxy3 = gsignond_plugin_proxy_factory_get_plugin(
+ factory, 123, "password");
+ fail_if(proxy1 == NULL || proxy2 == NULL || proxy3 == NULL);
+ fail_if(proxy1 != proxy3 || proxy1 == proxy2);
+ check_plugin_proxy(proxy1);
+ check_plugin_proxy(proxy2);
+
+ g_object_unref(factory);
+ g_object_unref(config);
+}
+END_TEST
+
+START_TEST (test_pluginproxyfactory_add)
+{
+ GSignondConfig* config = gsignond_config_new();
+ fail_if(config == NULL);
+
+ GSignondPluginProxyFactory* factory = gsignond_plugin_proxy_factory_new(config);
+ fail_if(factory == NULL);
+
+ GSignondPluginProxy* proxy = gsignond_plugin_proxy_new(config, "password");
+ fail_if (proxy == NULL);
+ fail_if(gsignond_plugin_proxy_factory_add_plugin(factory, 123, proxy) == FALSE);
+ fail_if(gsignond_plugin_proxy_factory_add_plugin(factory, 123, proxy) == TRUE);
+ fail_if(gsignond_plugin_proxy_factory_get_plugin(factory, 123, "password") != proxy);
+
+ g_object_unref(proxy);
+ g_object_unref(factory);
+ g_object_unref(config);
+}
+END_TEST
+
+
+Suite* pluginproxy_suite (void)
+{
+ Suite *s = suite_create ("Plugin proxy");
+
+ /* Core test case */
+ TCase *tc_core = tcase_create ("Tests");
+ tcase_add_test (tc_core, test_plugin_loader);
+ tcase_add_test (tc_core, test_pluginproxy_create);
+ tcase_add_test (tc_core, test_pluginproxy_process);
+ tcase_add_test (tc_core, test_pluginproxy_process_cancel);
+ //FIXME: we need an asynchronous or remote testing plugin to really test
+ // cancellation and queueuing. Password plugin is totally synchronous.
+ tcase_add_test (tc_core, test_pluginproxy_process_queue);
+ tcase_add_test (tc_core, test_pluginproxy_process_queue_cancel);
+ tcase_add_test (tc_core, test_pluginproxyfactory_get);
+ tcase_add_test (tc_core, test_pluginproxyfactory_add);
+ suite_add_tcase (s, tc_core);
+ return s;
+}
+
+int main (void)
+{
+ int number_failed;
+
+ g_type_init();
+
+ Suite *s = pluginproxy_suite();
+ SRunner *sr = srunner_create(s);
+ srunner_run_all(sr, CK_NORMAL);
+ number_failed = srunner_ntests_failed(sr);
+ srunner_free(sr);
+ return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+