plugind: separate process is completed; all the proxy unit tests are functional as...
authorImran Zaman <imran.zaman@linux.intel.com>
Thu, 11 Apr 2013 12:37:29 +0000 (15:37 +0300)
committerImran Zaman <imran.zaman@linux.intel.com>
Wed, 15 May 2013 12:29:06 +0000 (15:29 +0300)
33 files changed:
configure.ac
include/gsignond/gsignond-config-dbus.h
include/gsignond/gsignond-config-general.h
include/gsignond/gsignond-error.h
include/gsignond/gsignond-log.h
include/gsignond/gsignond-pipe-stream.h [new file with mode: 0644]
include/gsignond/gsignond-plugin-interface.h
include/gsignond/gsignond-plugin-loader.h
src/common/Makefile.am
src/common/gsignond-config.c
src/common/gsignond-dictionary.c
src/common/gsignond-error.c
src/common/gsignond-pipe-stream.c [new file with mode: 0644]
src/common/gsignond-plugin-interface.c
src/common/gsignond-plugin-loader.c
src/daemon/dbus/Makefile.am
src/daemon/dbus/gsignond-dbus.h
src/daemon/dbus/interfaces/com.google.code.AccountsSSO.gSingleSignOn.RemotePlugin.xml [new file with mode: 0644]
src/daemon/plugins/Makefile.am
src/daemon/plugins/gsignond-plugin-proxy-factory.c
src/daemon/plugins/gsignond-plugin-proxy.c
src/daemon/plugins/gsignond-plugin-proxy.h
src/daemon/plugins/gsignond-plugin-remote.c [new file with mode: 0644]
src/daemon/plugins/gsignond-plugin-remote.h [new file with mode: 0644]
src/daemon/plugins/plugind/Makefile.am [new file with mode: 0644]
src/daemon/plugins/plugind/gsignond-plugin-daemon.c [new file with mode: 0644]
src/daemon/plugins/plugind/gsignond-plugin-daemon.h [new file with mode: 0644]
src/daemon/plugins/plugind/main.c [new file with mode: 0644]
src/plugins/digest/gsignond-digest-plugin.c
src/plugins/password/gsignond-password-plugin.c
src/plugins/ssotest/gsignond-ssotest-plugin.c
test/plugins/Makefile.am
test/plugins/pluginproxytest.c

index a0a2a9b..7b8a7e3 100644 (file)
@@ -106,6 +106,7 @@ src/daemon/db/Makefile
 src/daemon/dbus/Makefile
 src/daemon/dbus/services/com.google.code.AccountsSSO.gSingleSignOn.service
 src/daemon/plugins/Makefile
+src/daemon/plugins/plugind/Makefile
 src/extensions/Makefile
 src/extensions/test/Makefile
 src/extensions/tizen/Makefile
index a6d8988..7b183fe 100644 (file)
@@ -34,5 +34,6 @@
                                                 "/IdentityTimeout"
 #define GSIGNOND_CONFIG_DBUS_AUTH_SESSION_TIMEOUT GSIGNOND_CONFIG_DBUS_TIMEOUTS \
                                                   "/AuthSessionTimeout"
-
+#define GSIGNOND_CONFIG_DBUS_PLUGIN_TIMEOUT     GSIGNOND_CONFIG_DBUS_TIMEOUTS \
+                                                  "/PluginTimeout"
 #endif /* __GSIGNOND_CONFIG_DBUS_H_ */
index 2ab2fd8..c7c7e67 100644 (file)
@@ -35,6 +35,8 @@
                                                 "/ExtensionsDir"
 #define GSIGNOND_CONFIG_GENERAL_PLUGINS_DIR     GSIGNOND_CONFIG_GENERAL \
                                                 "/PluginsDir"
+#define GSIGNOND_CONFIG_GENERAL_BIN_DIR         GSIGNOND_CONFIG_GENERAL \
+                                                "/BinDir"
 #define GSIGNOND_CONFIG_GENERAL_EXTENSION       GSIGNOND_CONFIG_GENERAL \
                                                 "/Extension"
 #define GSIGNOND_CONFIG_GENERAL_SECURE_DIR      GSIGNOND_CONFIG_GENERAL \
index e308571..aa94b29 100644 (file)
@@ -114,7 +114,16 @@ gsignond_concat_domain_and_error (
         const gchar *str2);
 
 GString*
-gsignond_prepend_domain_to_error_msg (const GError *err);
+gsignond_prepend_domain_to_error_msg (
+        const GError *err);
+
+GError *
+gsignond_error_new_from_variant (
+        GVariant *var);
+
+GVariant *
+gsignond_error_to_variant (
+        GError *error);
 
 #define gsignond_get_gerror_for_id(err, message, args...) \
     g_error_new (gsignond_error_quark(), err, message, ##args);
index d8202e9..85a5c59 100644 (file)
 
 #include <glib.h>
 
-#define INFO(frmt, args...) g_message("%s:%d  " frmt , __FILE__, __LINE__, ##args)
-#define ERR(frmt, args...)  g_error("%s:%d  " frmt , __FILE__, __LINE__, ##args)
-#define WARN(frmt, args...)  g_warning("%s:%d  " frmt , __FILE__, __LINE__, ##args)
-#define DBG(frmt, args...)  g_debug("%s:%d  " frmt , __FILE__, __LINE__, ##args)
+#define INFO(frmt, args...) g_message("%s:%d %s " frmt , __FILE__, __LINE__, \
+        __PRETTY_FUNCTION__, ##args)
+#define ERR(frmt, args...)  g_error("%s:%d %s " frmt , __FILE__, __LINE__, \
+        __PRETTY_FUNCTION__, ##args)
+#define WARN(frmt, args...)  g_warning("%s:%d %s " frmt , __FILE__, __LINE__, \
+        __PRETTY_FUNCTION__, ##args)
+#define DBG(frmt, args...)  g_debug("%s:%d %s " frmt , __FILE__, __LINE__, \
+        __PRETTY_FUNCTION__, ##args)
 
 #endif /* __GSIGNOND_LOG_H_ */
diff --git a/include/gsignond/gsignond-pipe-stream.h b/include/gsignond/gsignond-pipe-stream.h
new file mode 100644 (file)
index 0000000..05d1c0c
--- /dev/null
@@ -0,0 +1,78 @@
+/* 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) 2013 Intel Corporation.
+ *
+ * Contact: Imran Zaman <imran.zaman@linux.intel.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_PIPE_STREAM_H__
+#define __GSIGNOND_PIPE_STREAM_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+/*
+ * Type macros.
+ */
+#define GSIGNOND_TYPE_PIPE_STREAM   (gsignond_pipe_stream_get_type ())
+#define GSIGNOND_PIPE_STREAM(obj)   (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+                                           GSIGNOND_TYPE_PIPE_STREAM, \
+                                           GSignondPipeStream))
+#define GSIGNOND_IS_PIPE_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+                                           GSIGNOND_TYPE_PIPE_STREAM))
+#define GSIGNOND_PIPE_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+                                             GSIGNOND_TYPE_PIPE_STREAM, \
+                                             GSignondPipeStreamClass))
+#define GSIGNOND_IS_PIPE_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\
+                                             GSIGNOND_TYPE_PIPE_STREAM))
+#define GSIGNOND_PIPE_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+                                             GSIGNOND_TYPE_PIPE_STREAM, \
+                                             GSignondPipeStreamClass))
+
+typedef struct _GSignondPipeStreamPrivate GSignondPipeStreamPrivate;
+
+typedef struct {
+    GIOStream parent_instance;
+
+    /*< private >*/
+    GSignondPipeStreamPrivate *priv;
+} GSignondPipeStream;
+
+typedef struct {
+    GIOStreamClass parent_class;
+
+} GSignondPipeStreamClass;
+
+/* used by GSIGNOND_TYPE_PIPE_STREAM */
+GType
+gsignond_pipe_stream_get_type (void);
+
+GSignondPipeStream *
+gsignond_pipe_stream_new (
+        gint in_fd,
+        gint out_fd);
+
+G_END_DECLS
+
+#endif /* __GSIGNOND_PIPE_STREAM_H__ */
index ad15c0e..29bcdf2 100644 (file)
@@ -77,7 +77,6 @@ struct _GSignondPluginInterface {
     GTypeInterface parent;
 
     void (*cancel) (GSignondPlugin *self);
-    void (*abort) (GSignondPlugin *self);
     void (*request_initial) (GSignondPlugin *self, 
                      GSignondSessionData *session_data, 
                      const gchar *mechanism);
@@ -95,8 +94,6 @@ GType gsignond_plugin_get_type (void);
 void 
 gsignond_plugin_cancel (GSignondPlugin *self);
 void 
-gsignond_plugin_abort (GSignondPlugin *self);
-void 
 gsignond_plugin_request_initial (GSignondPlugin *self, 
                               GSignondSessionData *session_data, 
                               const gchar *mechanism);
index f2f7e07..0c1e727 100644 (file)
 G_BEGIN_DECLS
 
 GSignondPlugin*
-gsignond_load_plugin(GSignondConfig* config, gchar* plugin_type);
+gsignond_load_plugin(
+        GSignondConfig* config,
+        gchar* plugin_type);
+
+GSignondPlugin*
+gsignond_load_plugin_with_filename(
+        gchar *plugin_type,
+        gchar *plugin_filename);
 
 G_END_DECLS
 
-#endif /* _GSIGNOND_PLUGIN_LOADER_H_ */
\ No newline at end of file
+#endif /* _GSIGNOND_PLUGIN_LOADER_H_ */
+
index 704d0ed..c790211 100644 (file)
@@ -33,6 +33,7 @@ libgsignond_common_la_CPPFLAGS = \
     $(GSIGNOND_CFLAGS) \
     -DGSIGNOND_PLUGINS_DIR='"$(pluginsdir)"' \
     -DGSIGNOND_EXTENSIONS_DIR='"$(extensionsdir)"' \
+    -DGSIGNOND_BIN_DIR='"$(bindir)"' \
     $(NULL)
 
 libgsignond_common_la_DEPENDENCIES = \
@@ -59,6 +60,7 @@ libgsignond_common_la_SOURCES = \
     gsignond-signonui-data.c \
     gsignond-plugin-loader.c \
     gsignond-utils.c \
+    gsignond-pipe-stream.c \
     $(BUILT_SOURCES) \
     $(NULL)
 
index e4e1bf7..562b7cb 100644 (file)
@@ -86,9 +86,7 @@ _load_config (GSignondConfig *self)
                 def_config = g_build_filename (*sysconfdirs,
                                                "gsignond/gsignond.conf",
                                                NULL);
-                DBG ("try to load config from %s", def_config);
                 if (g_access (def_config, R_OK) == 0) {
-                    DBG ("use config from %s", def_config);
                     self->priv->config_file_path = def_config;
                     break;
                 }
@@ -203,6 +201,12 @@ _load_environment (GSignondConfig *self)
                                     GSIGNOND_CONFIG_GENERAL_EXTENSIONS_DIR,
                                     e_val);
 
+    e_val = g_getenv ("SSO_BIN_DIR");
+    if (e_val)
+        gsignond_config_set_string (self,
+                                    GSIGNOND_CONFIG_GENERAL_BIN_DIR,
+                                    e_val);
+
     e_val = g_getenv ("SSO_EXTENSION");
     if (e_val)
         gsignond_config_set_string (self,
@@ -313,6 +317,9 @@ gsignond_config_init (GSignondConfig *self)
     gsignond_config_set_string (self,
                                 GSIGNOND_CONFIG_GENERAL_EXTENSIONS_DIR,
                                 (GSIGNOND_EXTENSIONS_DIR));
+    gsignond_config_set_string (self,
+                             (GSIGNOND_CONFIG_GENERAL_BIN_DIR),
+                             (GSIGNOND_BIN_DIR));
 
     gchar *default_data_path =
         g_build_filename (g_get_user_data_dir (), "gsignond", NULL);
index aee2ea4..7d2c0c2 100644 (file)
@@ -24,6 +24,7 @@
  */
 
 #include <gsignond/gsignond-dictionary.h>
+#include <gsignond/gsignond-log.h>
 
 /**
  * gsignond_dictionary_new_from_variant:
@@ -170,7 +171,6 @@ gsignond_dictionary_set (GSignondDictionary *dict,
     g_return_val_if_fail (value != NULL, FALSE);
 
     g_variant_ref_sink(value);
-    
     g_hash_table_replace (
             dict,
             g_strdup(key),
index 245b07e..462b43c 100644 (file)
@@ -110,3 +110,49 @@ gsignond_prepend_domain_to_error_msg (const GError *err)
     return msg;
 }
 
+/**
+ * gsignond_error_new_from_variant:
+ * @var: instance of #GVariant
+ *
+ * Converts the GVariant to GError.
+ *
+ * Returns: (transfer full) #GError object if successful, NULL otherwise.
+ */
+GError *
+gsignond_error_new_from_variant (
+        GVariant *var)
+{
+    GError *error = NULL;
+    gchar *message;
+    GQuark domain;
+    gint code;
+
+    if (!var) {
+        return NULL;
+    }
+
+    g_variant_get (var, "(uis)", &domain, &code, &message);
+    error = g_error_new_literal (domain, code, message);
+    g_free (message);
+    return error;
+}
+
+/**
+ * gsignond_error_to_variant:
+ * @error: instance of #GError
+ *
+ * Converts the GError to GVariant.
+ *
+ * Returns: (transfer full) #GVariant object if successful, NULL otherwise.
+ */
+GVariant *
+gsignond_error_to_variant (
+        GError *error)
+{
+    if (!error) {
+        return NULL;
+    }
+
+    return g_variant_new ("(uis)", error->domain, error->code, error->message);
+}
+
diff --git a/src/common/gsignond-pipe-stream.c b/src/common/gsignond-pipe-stream.c
new file mode 100644 (file)
index 0000000..29901c3
--- /dev/null
@@ -0,0 +1,122 @@
+/* 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) 2013 Intel Corporation.
+ *
+ * Contact: Imran Zaman <imran.zaman@linux.intel.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 <gio/gunixinputstream.h>
+#include <gio/gunixoutputstream.h>
+
+#include "gsignond/gsignond-pipe-stream.h"
+
+#define GSIGNOND_PIPE_STREAM_GET_PRIVATE(obj) \
+                                          (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\
+                                           GSIGNOND_TYPE_PIPE_STREAM, \
+                                           GSignondPipeStreamPrivate))
+
+struct _GSignondPipeStreamPrivate
+{
+    GInputStream  *input_stream;
+    GOutputStream *output_stream;
+};
+
+G_DEFINE_TYPE (GSignondPipeStream, gsignond_pipe_stream, G_TYPE_IO_STREAM);
+
+static GInputStream *
+_gsignond_pipe_stream_get_input_stream (GIOStream *io_stream)
+{
+    return GSIGNOND_PIPE_STREAM (io_stream)->priv->input_stream;
+}
+
+static GOutputStream *
+_gsignond_pipe_stream_get_output_stream (GIOStream *io_stream)
+{
+    return GSIGNOND_PIPE_STREAM (io_stream)->priv->output_stream;
+}
+
+static void
+_gsignond_pipe_stream_dispose (GObject *gobject)
+{
+    g_return_if_fail (GSIGNOND_IS_PIPE_STREAM (gobject));
+
+    GSignondPipeStream *stream = GSIGNOND_PIPE_STREAM (gobject);
+
+    if (stream->priv->input_stream) {
+        g_object_unref (stream->priv->input_stream);
+        stream->priv->input_stream = NULL;
+    }
+
+    if (stream->priv->output_stream) {
+        g_object_unref (stream->priv->output_stream);
+        stream->priv->output_stream = NULL;
+    }
+
+    /* Chain up to the parent class */
+    G_OBJECT_CLASS (gsignond_pipe_stream_parent_class)->dispose (gobject);
+}
+
+static void
+_gsignond_pipe_stream_finalize (GObject *gobject)
+{
+    G_OBJECT_CLASS (gsignond_pipe_stream_parent_class)->finalize (gobject);
+}
+
+static void
+gsignond_pipe_stream_class_init (GSignondPipeStreamClass *klass)
+{
+    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+    GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
+
+    gobject_class->finalize = _gsignond_pipe_stream_finalize;
+    gobject_class->dispose = _gsignond_pipe_stream_dispose;
+
+    /* virtual methods */
+    stream_class->get_input_stream = _gsignond_pipe_stream_get_input_stream;
+    stream_class->get_output_stream = _gsignond_pipe_stream_get_output_stream;
+
+    g_type_class_add_private (klass, sizeof (GSignondPipeStreamPrivate));
+}
+
+static void
+gsignond_pipe_stream_init (GSignondPipeStream *self)
+{
+    self->priv = GSIGNOND_PIPE_STREAM_GET_PRIVATE (self);
+    self->priv->input_stream = NULL;
+    self->priv->output_stream = NULL;
+}
+
+GSignondPipeStream *
+gsignond_pipe_stream_new (
+        gint in_fd,
+        gint out_fd)
+{
+    GSignondPipeStream *stream = GSIGNOND_PIPE_STREAM (g_object_new (
+            GSIGNOND_TYPE_PIPE_STREAM, NULL));
+    if (stream) {
+        stream->priv->input_stream = (GInputStream *)
+                    g_unix_input_stream_new (in_fd, TRUE);
+        stream->priv->output_stream = (GOutputStream *)
+                    g_unix_output_stream_new (out_fd, TRUE);
+    }
+    return stream;
+}
+
+
index 664f1f9..fa9d131 100644 (file)
@@ -76,15 +76,13 @@ static void gsignond_plugin_default_init (GSignondPluginInterface *g_class)
         G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE,
         2, GSIGNOND_TYPE_PLUGIN_STATE, G_TYPE_STRING);
 
-    g_object_interface_install_property (g_class,
-       g_param_spec_string ("type", "Type", "Plugin type", "none", 
-                             G_PARAM_READABLE|G_PARAM_STATIC_STRINGS));
-
-     g_object_interface_install_property (g_class,
-        g_param_spec_boxed ("mechanisms", "Mechanisms", 
-                            "List of plugin mechanisms", 
-                            G_TYPE_STRV, G_PARAM_READABLE|
-                                         G_PARAM_STATIC_STRINGS));
+    g_object_interface_install_property (g_class, g_param_spec_string ("type",
+            "Type", "Plugin type", "none",
+            G_PARAM_READABLE|G_PARAM_STATIC_STRINGS));
+
+    g_object_interface_install_property (g_class, g_param_spec_boxed (
+            "mechanisms", "Mechanisms", "List of plugin mechanisms",
+            G_TYPE_STRV, G_PARAM_READABLE|G_PARAM_STATIC_STRINGS));
     
 }
 
@@ -95,20 +93,14 @@ void gsignond_plugin_cancel (GSignondPlugin *self)
     GSIGNOND_PLUGIN_GET_INTERFACE (self)->cancel (self);
 }
 
-void gsignond_plugin_abort (GSignondPlugin *self)
-{
-    g_return_if_fail (GSIGNOND_IS_PLUGIN (self));
-    
-    GSIGNOND_PLUGIN_GET_INTERFACE (self)->abort (self);
-}
-
 void gsignond_plugin_request_initial (GSignondPlugin *self, 
                               GSignondSessionData *session_data, 
                               const gchar *mechanism)
 {
     g_return_if_fail (GSIGNOND_IS_PLUGIN (self));
     
-    GSIGNOND_PLUGIN_GET_INTERFACE (self)->request_initial (self, session_data, mechanism);
+    GSIGNOND_PLUGIN_GET_INTERFACE (self)->request_initial (self, session_data,
+            mechanism);
 }
 
 void gsignond_plugin_request (GSignondPlugin *self, 
@@ -171,8 +163,8 @@ void gsignond_plugin_refreshed (GSignondPlugin *self,
     g_signal_emit (self, signals[REFRESHED], 0, ui_data);
 }
 
-void gsignond_plugin_status_changed (GSignondPlugin *self, GSignondPluginState state, 
-                                     const gchar *message)
+void gsignond_plugin_status_changed (GSignondPlugin *self,
+        GSignondPluginState state, const gchar *message)
 {
     g_signal_emit (self, signals[STATUS_CHANGED], 0, state, message);
 }
index 07909ca..1ded64b 100644 (file)
 #include <gmodule.h>
 
 GSignondPlugin*
-gsignond_load_plugin(GSignondConfig* config, gchar* plugin_type)
+gsignond_load_plugin(
+        GSignondConfig* config,
+        gchar* plugin_type)
 {
     gchar* plugin_filename = g_module_build_path (
-        gsignond_config_get_string (config, 
-        GSIGNOND_CONFIG_GENERAL_PLUGINS_DIR), 
-        plugin_type);
+            gsignond_config_get_string (config,
+                    GSIGNOND_CONFIG_GENERAL_PLUGINS_DIR), plugin_type);
+    GSignondPlugin *plugin = gsignond_load_plugin_with_filename (plugin_type,
+            plugin_filename);
+    g_free(plugin_filename);
+    return plugin;
+}
+
+GSignondPlugin*
+gsignond_load_plugin_with_filename(
+        gchar *plugin_type,
+        gchar *plugin_filename)
+{
     DBG("Loading plugin %s", plugin_filename);
     GModule* plugin_module = g_module_open (plugin_filename, 
-        G_MODULE_BIND_LOCAL);
-    g_free(plugin_filename);
+            G_MODULE_BIND_LOCAL);
     if (plugin_module == NULL) {
         DBG("Plugin couldn't be opened: %s", g_module_error());
         return NULL;
     }
-    
+
     gchar* plugin_get_type = g_strdup_printf("gsignond_%s_plugin_get_type",
         plugin_type);
     gpointer p;
index c25cda8..ae0eeea 100644 (file)
@@ -10,6 +10,8 @@ DBUS_BUILT_SOURCES = \
     gsignond-dbus-identity-gen.h \
     gsignond-dbus-signonui-gen.c \
     gsignond-dbus-signonui-gen.h \
+    gsignond-dbus-remote-plugin-gen.c \
+    gsignond-dbus-remote-plugin-gen.h \
     $(NULL)
 
 DBUS_BUILT_DOCS = \
@@ -17,6 +19,7 @@ DBUS_BUILT_DOCS = \
     gsignond-dbus-auth-session-doc-gen-com.google.code.AccountsSSO.gSingleSignOn.AuthSession.xml \
     gsignond-dbus-identity-doc-gen-com.google.code.AccountsSSO.gSingleSignOn.Identity.xml \
     gsignond-dbus-signonui-doc-gen-org.tizen.SSO.singlesignonui.xml \
+    gsignond-dbus-remote-plugin-doc-gen-com.google.code.AccountsSSO.gSingleSignOn.RemotePlugin.xml \
     $(NULL)
 
 DBUS_INTERFACE_PREFIX="com.google.code.AccountsSSO.gSingleSignOn."
@@ -52,6 +55,14 @@ gsignond-dbus-signonui-gen.c gsignond-dbus-signonui-gen.h : $(INTERFACES_DIR)/or
        --generate-docbook gsignond-dbus-signonui-doc-gen\
        $<
 
+gsignond-dbus-remote-plugin-gen.c gsignond-dbus-remote-plugin-gen.h : $(INTERFACES_DIR)/com.google.code.AccountsSSO.gSingleSignOn.RemotePlugin.xml
+       gdbus-codegen                                       \
+       --interface-prefix $(DBUS_INTERFACE_PREFIX)      \
+       --c-namespace GSignondDbus                           \
+       --generate-c-code  gsignond-dbus-remote-plugin-gen         \
+       --generate-docbook gsignond-dbus-remote-plugin-doc-gen     \
+       $<
+
 lib_LTLIBRARIES = libgsignond-dbus-glue.la
 
 libgsignond_dbus_glue_la_CPPFLAGS = \
@@ -105,7 +116,8 @@ dbusinterfaces_DATA = \
     $(INTERFACES_DIR)/com.google.code.AccountsSSO.gSingleSignOn.AuthService.xml \
     $(INTERFACES_DIR)/com.google.code.AccountsSSO.gSingleSignOn.AuthSession.xml \
     $(INTERFACES_DIR)/com.google.code.AccountsSSO.gSingleSignOn.Identity.xml \
-    $(INTERFACES_DIR)/org.tizen.SSO.singlesignonui.xml
+    $(INTERFACES_DIR)/org.tizen.SSO.singlesignonui.xml \
+    $(INTERFACES_DIR)/com.google.code.AccountsSSO.gSingleSignOn.RemotePlugin.xml
 
 EXTRA_DIST = dbusservice
 
index 3decf61..0d74902 100644 (file)
@@ -36,6 +36,7 @@
 #define GSIGNOND_DAEMON_INTERFACE        GSIGNOND_SERVICE_PREFIX ".AuthService"
 #define GSIGNOND_IDENTITY_INTERFACE      GSIGNOND_SERVICE_PREFIX ".Identity"
 #define GSIGNOND_AUTH_SESSION_INTERFACE  GSIGNOND_SERVICE_PREFIX ".AuthSession"
+#define GSIGNOND_PLUGIN_OBJECTPATH       GSIGNOND_DAEMON_OBJECTPATH "/Plugin"
 
 #define SIGNONUI_SERVICE                 "org.tizen.SSO"
 #define SIGNONUI_OBJECTPATH              "/org/tizen/SSO/SignonUi"
diff --git a/src/daemon/dbus/interfaces/com.google.code.AccountsSSO.gSingleSignOn.RemotePlugin.xml b/src/daemon/dbus/interfaces/com.google.code.AccountsSSO.gSingleSignOn.RemotePlugin.xml
new file mode 100644 (file)
index 0000000..a7b97d2
--- /dev/null
@@ -0,0 +1,47 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+  <interface name="com.google.code.AccountsSSO.gSingleSignOn.RemotePlugin">
+    <method name="cancel">
+    </method>
+    <method name="requestInitial">
+      <arg name="sessionData" type="a{sv}" direction="in"/>
+      <arg name="mechanism" type="s" direction="in"/>
+    </method>
+    <method name="request">
+      <arg name="sessionData" type="a{sv}" direction="in"/>
+    </method>
+    <method name="userActionFinished">
+      <arg name="uiData" type="a{sv}" direction="in"/>
+    </method>
+    <method name="refresh">
+      <arg name="uiData" type="a{sv}" direction="in"/>
+    </method>
+    <method name="getInfo">
+      <arg name="type" type="s" direction="out"/>
+      <arg name="mechanisms" type="as" direction="out"/>
+    </method>
+        
+    <signal name="response">
+      <arg name="sessionData" type="a{sv}" direction="out"/>
+    </signal>
+    <signal name="responseFinal">
+      <arg name="sessionData" type="a{sv}" direction="out"/>
+    </signal>
+    <signal name="store">
+      <arg name="sessionData" type="a{sv}" direction="out"/>
+    </signal>
+    <signal name="error">
+      <arg name="error" type="(uis)" direction="out"/>
+    </signal>
+    <signal name="userActionRequired">
+      <arg name="uiData" type="a{sv}" direction="out"/>
+    </signal>
+    <signal name="refreshed">
+      <arg name="uiData" type="a{sv}" direction="out"/>
+    </signal>
+    <signal name="statusChanged">
+      <arg name="state" type="i" direction="out"/>
+      <arg name="message" type="s" direction="out"/>
+    </signal>
+  </interface>
+</node>
index fbf23e7..3ae2d61 100644 (file)
@@ -1,3 +1,5 @@
+SUBDIRS = plugind
+
 lib_LTLIBRARIES = libgsignond-plugins.la
 
 libgsignond_plugins_la_CPPFLAGS = \
@@ -8,10 +10,12 @@ libgsignond_plugins_la_CPPFLAGS = \
 
 libgsignond_plugins_la_LIBADD =    \
         $(top_srcdir)/src/common/libgsignond-common.la \
+        $(top_srcdir)/src/daemon/dbus/libgsignond-dbus-glue.la \
         $(GSIGNOND_LIBS)
 
 libgsignond_plugins_la_SOURCES = \
    gsignond-plugin-proxy.c \
-   gsignond-plugin-proxy-factory.c
+   gsignond-plugin-proxy-factory.c \
+   gsignond-plugin-remote.c
 
 CLEANFILES = 
index fe2e37c..42340e2 100644 (file)
@@ -28,6 +28,7 @@
 #include <stdio.h>
 #include <gsignond/gsignond-log.h>
 #include <gsignond/gsignond-plugin-loader.h>
+#include "gsignond-plugin-remote.h"
 
 G_DEFINE_TYPE (GSignondPluginProxyFactory, gsignond_plugin_proxy_factory, G_TYPE_OBJECT);
 
@@ -87,7 +88,6 @@ static void _enumerate_plugins(GSignondPluginProxyFactory* self)
                 if (g_strcmp0 (plugin_type, plugin_name) == 0) {
                     *method_iter = plugin_type;
                     method_iter++;
-                    DBG ("method %s (%p)", plugin_type, plugin);
                     g_hash_table_insert(self->mechanisms,
                         plugin_type, mechanisms);
                 } else {
@@ -115,11 +115,6 @@ gsignond_plugin_proxy_factory_constructor (GType                  gtype,
         gtype, n_properties, properties);
   }
   
-  /* update the object state depending on constructor properties */
-  GSignondPluginProxyFactory* self = GSIGNOND_PLUGIN_PROXY_FACTORY(obj);
-  
-  _enumerate_plugins(self);
-
   return obj;
 }
 
@@ -293,7 +288,10 @@ const gchar**
 gsignond_plugin_proxy_factory_get_plugin_types(
    GSignondPluginProxyFactory* factory)
 {
-    return (gpointer)factory->methods;
+       if (factory->methods == NULL) {
+               _enumerate_plugins (factory);
+       }
+    return (const gchar**)factory->methods;
 }
    
 const gchar**
@@ -302,5 +300,20 @@ gsignond_plugin_proxy_factory_get_plugin_mechanisms(
 {
     g_return_val_if_fail(factory->mechanisms, NULL);
 
-    return g_hash_table_lookup(factory->mechanisms, plugin_type);
+    const gchar **mechanisms = NULL;
+    mechanisms = g_hash_table_lookup(factory->mechanisms, plugin_type);
+    if (mechanisms == NULL) {
+       GSignondPlugin* plugin = GSIGNOND_PLUGIN (gsignond_plugin_remote_new (
+               factory->config, plugin_type));
+       if (plugin != NULL) {
+               gchar **mechs = NULL;
+               g_object_get (plugin, "mechanisms", &mechs, NULL);
+               if (mechs != NULL) {
+                       g_hash_table_insert(factory->mechanisms, g_strdup(plugin_type),
+                               mechs);
+                       mechanisms = (const gchar **)mechs;
+               }
+       }
+    }
+    return mechanisms;
 }
index 6289054..4ce93c4 100644 (file)
  */
 
 #include "gsignond-plugin-proxy.h"
-#include <gsignond/gsignond-plugin-loader.h>
-#include <gsignond/gsignond-error.h>
-#include <gsignond/gsignond-log.h>
-#include "../gsignond-auth-session.h"
+#include "gsignond/gsignond-plugin-loader.h"
+#include "gsignond/gsignond-error.h"
+#include "gsignond/gsignond-log.h"
+#include "gsignond/gsignond-config.h"
+#include "daemon/gsignond-auth-session.h"
+#include "gsignond-plugin-remote.h"
 
 #define GSIGNOND_PLUGIN_PROXY_PRIV(obj) \
     G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
@@ -67,46 +69,24 @@ static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
 
 G_DEFINE_TYPE (GSignondPluginProxy, gsignond_plugin_proxy, G_TYPE_OBJECT);
 
-static void gsignond_plugin_proxy_response_final_callback(GSignondPlugin* plugin, 
-                                                  GSignondSessionData* result,
-                                                  gpointer user_data);
-static void gsignond_plugin_proxy_response_callback(GSignondPlugin* plugin, 
-                                                  GSignondSessionData* result,
-                                                  gpointer user_data);
-static void gsignond_plugin_proxy_store_callback(GSignondPlugin* plugin, 
-                                                  GSignondDictionary* token_data,
-                                                  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, 
-                                          GSignondSignonuiData* 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, 
-                                                  GSignondPluginState status,
-                                                  const gchar* message,
-                                                  gpointer user_data);
-
-static GSignondProcessData* 
-gsignond_process_data_new (GSignondAuthSession* auth_session,
-                           GSignondSessionData *session_data,
-                           const gchar* mechanism,
-                           gpointer userdata) 
+static GSignondProcessData*
+gsignond_process_data_new (
+        GSignondAuthSession* auth_session,
+        GSignondSessionData *session_data,
+        const gchar* mechanism,
+        gpointer userdata)
 {
     GSignondProcessData* data = g_slice_new0 (GSignondProcessData);
-    g_object_ref (auth_session);
-    data->auth_session = auth_session;
+    data->auth_session = g_object_ref (auth_session);
     data->session_data = gsignond_dictionary_copy (session_data);
     data->mechanism = g_strdup (mechanism);
     data->userdata = userdata;
     return data;
 }
 
-static void gsignond_process_data_free (GSignondProcessData* data)
+static void
+gsignond_process_data_free (
+        GSignondProcessData* data)
 {
     g_object_unref (data->auth_session);
     gsignond_dictionary_unref (data->session_data);
@@ -114,10 +94,182 @@ static void gsignond_process_data_free (GSignondProcessData* data)
     g_slice_free (GSignondProcessData, data);
 }
 
+static void
+gsignond_plugin_proxy_process_queue (
+        GSignondPluginProxy *self)
+{
+    g_assert (GSIGNOND_IS_PLUGIN_PROXY (self));
+
+    GSignondPluginProxyPrivate *priv = self->priv;
+    GSignondProcessData* next_data = g_queue_pop_head (priv->session_queue);
+    if (next_data) {
+        priv->expecting_request = FALSE;
+        priv->active_process_userdata = next_data->userdata;
+        priv->active_session = next_data->auth_session;
+        g_object_ref (priv->active_session);
+        gsignond_auth_session_notify_state_changed (
+                priv->active_session, GSIGNOND_PLUGIN_STATE_STARTED,
+                "The request is being processed.",
+                priv->active_process_userdata);
+        gsignond_plugin_request_initial (priv->plugin,
+                                         next_data->session_data,
+                                         next_data->mechanism);
+        gsignond_process_data_free (next_data);
+    }
+}
+
+static void
+gsignond_plugin_proxy_response_final_callback (
+        GSignondPlugin *plugin,
+        GSignondSessionData *result,
+        gpointer user_data)
+{
+    GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (user_data);
+    GSignondPluginProxyPrivate *priv = self->priv;
+
+    DBG ("");
+    if (priv->active_session == NULL) {
+        WARN("Error: plugin %s reported 'response_final', but no active session"
+                " in plugin proxy", priv->plugin_type);
+        return;
+    }
+    gsignond_auth_session_notify_process_result (priv->active_session, result,
+            priv->active_process_userdata);
+    g_object_unref (priv->active_session);
+    priv->active_session = NULL;
+    priv->active_process_userdata = NULL;
+    gsignond_plugin_proxy_process_queue (self);
+}
+
+static void
+gsignond_plugin_proxy_response_callback(
+        GSignondPlugin *plugin,
+        GSignondSessionData *result,
+        gpointer user_data)
+{
+    GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (user_data);
+    GSignondPluginProxyPrivate *priv = self->priv;
+
+    if (priv->active_session == NULL) {
+        WARN("Error: plugin %s reported 'response', but no active session "
+                "in plugin proxy", priv->plugin_type);
+        return;
+    }
+    priv->expecting_request = TRUE;
+    gsignond_auth_session_notify_process_result (priv->active_session,
+            result, priv->active_process_userdata);
+}
+
+static void
+gsignond_plugin_proxy_store_callback (
+        GSignondPlugin *plugin,
+        GSignondSessionData *result,
+        gpointer user_data)
+{
+    GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (user_data);
+    GSignondPluginProxyPrivate *priv = self->priv;
+
+    if (priv->active_session == NULL) {
+        WARN("Error: plugin %s reported 'store', but no active session "
+                "in plugin proxy", priv->plugin_type);
+        return;
+    }
+    gsignond_auth_session_notify_store (priv->active_session, result);
+}
+
+static void
+gsignond_plugin_proxy_refreshed_callback (
+        GSignondPlugin *plugin,
+        GSignondSignonuiData *ui_result,
+        gpointer user_data)
+{
+    GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (user_data);
+    GSignondPluginProxyPrivate *priv = self->priv;
+
+    if (priv->active_session == NULL) {
+        WARN("Error: plugin %s reported 'refreshed', but no active session"
+                " in plugin proxy", priv->plugin_type);
+        return;
+    }
+    gsignond_auth_session_notify_refreshed (priv->active_session, ui_result);
+}
+
+static void
+gsignond_plugin_proxy_user_action_required_callback (
+        GSignondPlugin *plugin,
+        GSignondSignonuiData *ui_request,
+        gpointer user_data)
+{
+    GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (user_data);
+    GSignondPluginProxyPrivate *priv = self->priv;
+
+    if (priv->active_session == NULL) {
+        WARN("Error: plugin %s reported 'user_action_required', but no active"
+                " session in plugin proxy", priv->plugin_type);
+        return;
+    }
+    gsignond_auth_session_notify_user_action_required(
+        priv->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);
+    GSignondPluginProxyPrivate *priv = self->priv;
+
+    if (priv->active_session == NULL) {
+        WARN("Error: plugin %s reported error %s, but no active session "
+                "in plugin proxy", priv->plugin_type, error->message);
+        return;
+    }
+    gsignond_auth_session_notify_process_error (priv->active_session, error,
+            priv->active_process_userdata);
+    g_object_unref (priv->active_session);
+    priv->active_session = NULL;
+    priv->active_process_userdata = NULL;
+    gsignond_plugin_proxy_process_queue (self);
+}
+
+static void
+gsignond_plugin_proxy_status_changed_callback (
+        GSignondPlugin *plugin,
+        GSignondPluginState state,
+        const gchar *message,
+        gpointer user_data)
+{
+    GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (user_data);
+    GSignondPluginProxyPrivate *priv = self->priv;
+
+    if (priv->active_session == NULL) {
+        WARN("Error: plugin %s reported change in state %d with message %s, "
+                "but no active session in plugin proxy", priv->plugin_type,
+                state, message);
+        return;
+    }
+    gsignond_auth_session_notify_state_changed (priv->active_session,
+                                                (gint) state, message,
+                                                priv->active_process_userdata);
+}
+
+static void
+gsignond_plugin_proxy_user_action_finished_triggered_cb(
+        GSignondPluginRemote* plugin,
+        gpointer user_data)
+{
+    GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (user_data);
+
+    gsignond_plugin_proxy_process_queue (self);
+}
+
 static GObject *
-gsignond_plugin_proxy_constructor (GType                  gtype,
-                                   guint                  n_properties,
-                                   GObjectConstructParam *properties)
+gsignond_plugin_proxy_constructor (
+        GType                  gtype,
+        guint                  n_properties,
+        GObjectConstructParam *properties)
 {
     GObject *obj;
 
@@ -128,20 +280,15 @@ gsignond_plugin_proxy_constructor (GType                  gtype,
     /* update the object state depending on constructor properties */
     GSignondPluginProxy* self = GSIGNOND_PLUGIN_PROXY (obj);
     GSignondPluginProxyPrivate *priv = self->priv;
-    priv->plugin = gsignond_load_plugin (priv->config,
-                                         priv->plugin_type);
+    priv->plugin = GSIGNOND_PLUGIN (gsignond_plugin_remote_new (priv->config,
+            priv->plugin_type));
 
     if (priv->plugin == NULL) {
         g_free (priv->plugin_type);
         priv->plugin_type = NULL;
+
     } else {
-        gchar *type;
-        g_object_get (priv->plugin, "type", &type, NULL);
-        if (g_strcmp0 (type, priv->plugin_type) != 0) {
-            g_free (priv->plugin_type);
-            priv->plugin_type = NULL;
-        }
-        g_free (type);
+        gchar *type = NULL;
 
         g_signal_connect(priv->plugin, "response", G_CALLBACK(
             gsignond_plugin_proxy_response_callback), self);
@@ -157,15 +304,29 @@ gsignond_plugin_proxy_constructor (GType                  gtype,
             gsignond_plugin_proxy_refreshed_callback), self);
         g_signal_connect(priv->plugin, "status-changed", G_CALLBACK(
             gsignond_plugin_proxy_status_changed_callback), self);
+
+        g_signal_connect(GSIGNOND_PLUGIN_REMOTE (priv->plugin),
+                "user-action-finished-triggered", G_CALLBACK(
+                gsignond_plugin_proxy_user_action_finished_triggered_cb),
+                self);
+
+        g_object_get (priv->plugin, "type", &type, NULL);
+        if (g_strcmp0 (type, priv->plugin_type) != 0) {
+            g_free (priv->plugin_type);
+            priv->plugin_type = NULL;
+        }
+        g_free (type);
+
     }
     return obj;
 }
 
 static void
-gsignond_plugin_proxy_set_property (GObject      *object,
-                                    guint         property_id,
-                                    const GValue *value,
-                                    GParamSpec   *pspec)
+gsignond_plugin_proxy_set_property (
+        GObject      *object,
+        guint         property_id,
+        const GValue *value,
+        GParamSpec   *pspec)
 {
     GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (object);
     GSignondPluginProxyPrivate *priv = self->priv;
@@ -187,10 +348,11 @@ gsignond_plugin_proxy_set_property (GObject      *object,
 }
 
 static void
-gsignond_plugin_proxy_get_property (GObject    *object,
-                                    guint       prop_id,
-                                    GValue     *value,
-                                    GParamSpec *pspec)
+gsignond_plugin_proxy_get_property (
+        GObject    *object,
+        guint       prop_id,
+        GValue     *value,
+        GParamSpec *pspec)
 {
     GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (object);
     GSignondPluginProxyPrivate *priv = self->priv;
@@ -214,7 +376,8 @@ gsignond_plugin_proxy_get_property (GObject    *object,
 }
 
 static void
-gsignond_plugin_proxy_dispose (GObject *gobject)
+gsignond_plugin_proxy_dispose (
+        GObject *gobject)
 {
     GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (gobject);
     GSignondPluginProxyPrivate *priv = self->priv;
@@ -259,7 +422,8 @@ gsignond_plugin_proxy_finalize (GObject *gobject)
 
 
 static void
-gsignond_plugin_proxy_class_init (GSignondPluginProxyClass *klass)
+gsignond_plugin_proxy_class_init (
+        GSignondPluginProxyClass *klass)
 {
     GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
@@ -285,7 +449,6 @@ gsignond_plugin_proxy_class_init (GSignondPluginProxyClass *klass)
                             "List of plugin mechanisms", 
                             G_TYPE_STRV, G_PARAM_READABLE);
 
-
     obj_properties[PROP_CONFIG] = g_param_spec_object ("config",
                                                    "config",
                                                    "Configuration object",
@@ -294,14 +457,15 @@ gsignond_plugin_proxy_class_init (GSignondPluginProxyClass *klass)
                                                    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)
+gsignond_plugin_proxy_init (
+        GSignondPluginProxy *self)
 {
     GSignondPluginProxyPrivate *priv = GSIGNOND_PLUGIN_PROXY_PRIV (self);
     self->priv = priv;
@@ -316,7 +480,8 @@ gsignond_plugin_proxy_init (GSignondPluginProxy *self)
 }
 
 static const gchar *
-gsignond_plugin_proxy_get_plugin_type (GSignondPluginProxy *self)
+gsignond_plugin_proxy_get_plugin_type (
+        GSignondPluginProxy *self)
 {
     g_assert (GSIGNOND_IS_PLUGIN_PROXY (self));
 
@@ -324,7 +489,9 @@ gsignond_plugin_proxy_get_plugin_type (GSignondPluginProxy *self)
 }
 
 GSignondPluginProxy* 
-gsignond_plugin_proxy_new (GSignondConfig *config, const gchar *plugin_type)
+gsignond_plugin_proxy_new (
+        GSignondConfig *config,
+        const gchar *plugin_type)
 {
     GSignondPluginProxy* proxy = g_object_new (GSIGNOND_TYPE_PLUGIN_PROXY,
                                                "config", config,
@@ -338,35 +505,13 @@ gsignond_plugin_proxy_new (GSignondConfig *config, const gchar *plugin_type)
     return NULL;
 }
 
-static void
-gsignond_plugin_proxy_process_queue (GSignondPluginProxy *self)
-{
-    g_assert (GSIGNOND_IS_PLUGIN_PROXY (self));
-
-    GSignondPluginProxyPrivate *priv = self->priv;
-    GSignondProcessData* next_data = g_queue_pop_head (priv->session_queue);
-    if (next_data) {
-        priv->expecting_request = FALSE;
-        priv->active_process_userdata = next_data->userdata;
-        priv->active_session = next_data->auth_session;
-        g_object_ref (priv->active_session);
-        gsignond_auth_session_notify_state_changed (
-                                            priv->active_session,
-                                            GSIGNOND_PLUGIN_STATE_STARTED,
-                                            "The request is being processed.",
-                                            priv->active_process_userdata);
-        gsignond_plugin_request_initial (priv->plugin,
-                                         next_data->session_data, 
-                                         next_data->mechanism);
-        gsignond_process_data_free (next_data);
-    }
-}
-
-void gsignond_plugin_proxy_process (GSignondPluginProxy *self, 
-                                    GSignondAuthSession *session,
-                                    GSignondSessionData *session_data, 
-                                    const gchar *mechanism,
-                                    gpointer userdata)
+void
+gsignond_plugin_proxy_process (
+        GSignondPluginProxy *self,
+        GSignondAuthSession *session,
+        GSignondSessionData *session_data,
+        const gchar *mechanism,
+        gpointer userdata)
 {
     g_assert (GSIGNOND_IS_PLUGIN_PROXY (self));
     g_assert (GSIGNOND_IS_AUTH_SESSION (session));
@@ -385,17 +530,17 @@ void gsignond_plugin_proxy_process (GSignondPluginProxy *self,
                                                   session_data,
                                                   mechanism, userdata));
     gsignond_auth_session_notify_state_changed (
-                                         session,
-                                         GSIGNOND_PLUGIN_STATE_PROCESS_PENDING,
-                                         "The request has been queued.", userdata);
+            session, GSIGNOND_PLUGIN_STATE_PROCESS_PENDING,
+            "The request has been queued.", userdata);
     if (priv->active_session == NULL) {
         gsignond_plugin_proxy_process_queue (self);
     }
 }
 
 static gint
-gsignond_plugin_proxy_compare_process_data (gconstpointer process_data,
-                                            gconstpointer auth_session)
+gsignond_plugin_proxy_compare_process_data (
+        gconstpointer process_data,
+        gconstpointer auth_session)
 {
     g_return_val_if_fail (process_data && auth_session, 0);
 
@@ -406,8 +551,9 @@ gsignond_plugin_proxy_compare_process_data (gconstpointer process_data,
 }
 
 static GSignondProcessData*
-gsignond_plugin_proxy_find_by_session_iface (GSignondPluginProxy *self, 
-                                             GSignondAuthSession *session)
+gsignond_plugin_proxy_find_by_session_iface (
+        GSignondPluginProxy *self,
+        GSignondAuthSession *session)
 {
     g_assert (GSIGNOND_IS_PLUGIN_PROXY (self));
 
@@ -418,8 +564,9 @@ gsignond_plugin_proxy_find_by_session_iface (GSignondPluginProxy *self,
 }
 
 void 
-gsignond_plugin_proxy_cancel (GSignondPluginProxy *self, 
-                              GSignondAuthSession *session)
+gsignond_plugin_proxy_cancel (
+        GSignondPluginProxy *self,
+        GSignondAuthSession *session)
 {
     g_assert (GSIGNOND_IS_PLUGIN_PROXY (self));
     g_assert (GSIGNOND_IS_AUTH_SESSION (session));
@@ -429,10 +576,6 @@ gsignond_plugin_proxy_cancel (GSignondPluginProxy *self,
     /* cancel active session */
     if (session == priv->active_session) {
         gsignond_plugin_cancel (priv->plugin);
-        g_object_unref (priv->active_session);
-        priv->active_session = NULL;
-        priv->active_process_userdata = NULL;
-        gsignond_plugin_proxy_process_queue (self);
     } else { /* cancel by de-queue */
         GSignondProcessData* data =
             gsignond_plugin_proxy_find_by_session_iface (self, session);
@@ -450,160 +593,33 @@ gsignond_plugin_proxy_cancel (GSignondPluginProxy *self,
 }
 
 void
-gsignond_plugin_proxy_user_action_finished (GSignondPluginProxy *self,
-                                            GSignondSignonuiData *ui_data)
+gsignond_plugin_proxy_user_action_finished (
+        GSignondPluginProxy *self,
+        GSignondSignonuiData *ui_data)
 {
     g_assert (GSIGNOND_IS_PLUGIN_PROXY (self));
 
     if (self->priv->active_session == NULL) {
-        ERR("Error: 'user_action_finished' requested for plugin %s but no \
-            active session", self->priv->plugin_type);
+        WARN("Error: 'user_action_finished' requested for plugin %s but no "
+                "active session", self->priv->plugin_type);
         return;
     }
     gsignond_plugin_user_action_finished (self->priv->plugin, ui_data);
 }
 
 void
-gsignond_plugin_proxy_refresh (GSignondPluginProxy *self, 
-                               GSignondSignonuiData *ui_data)
+gsignond_plugin_proxy_refresh (
+        GSignondPluginProxy *self,
+        GSignondSignonuiData *ui_data)
 {
     g_assert (GSIGNOND_IS_PLUGIN_PROXY (self));
 
     if (self->priv->active_session == NULL) {
-        ERR("Error: 'refresh' requested for plugin %s but no active session",
-            self->priv->plugin_type);
+        WARN("Error: 'refresh' requested for plugin %s but no active session",
+                self->priv->plugin_type);
         return;
     }
     gsignond_plugin_refresh (self->priv->plugin, ui_data);
 }
 
-static void
-gsignond_plugin_proxy_response_final_callback (GSignondPlugin *plugin,
-                                               GSignondSessionData *result,
-                                               gpointer user_data)
-{
-    GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (user_data);
-    GSignondPluginProxyPrivate *priv = self->priv;
-
-    if (priv->active_session == NULL) {
-        ERR("Error: plugin %s reported 'response_final', but no active session \
-            in plugin proxy", priv->plugin_type);
-        return;
-    }
-    // This avoids problems if cancel() is called from AuthSession handler
-    GSignondAuthSession* active_session = priv->active_session;
-    priv->active_session = NULL;
-    gsignond_auth_session_notify_process_result (active_session, result, priv->active_process_userdata);
-    g_object_unref (active_session);
-    gsignond_plugin_proxy_process_queue (self);
-}
-
-static void
-gsignond_plugin_proxy_response_callback(GSignondPlugin *plugin, 
-                                        GSignondSessionData *result,
-                                        gpointer user_data)
-{
-    GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (user_data);
-    GSignondPluginProxyPrivate *priv = self->priv;
-
-    if (priv->active_session == NULL) {
-        ERR("Error: plugin %s reported 'response', but no active session \
-            in plugin proxy", priv->plugin_type);
-        return;
-    }
-    priv->expecting_request = TRUE;
-    gsignond_auth_session_notify_process_result (priv->active_session,
-                                                       result, priv->active_process_userdata);
-}
-
-static void
-gsignond_plugin_proxy_store_callback (GSignondPlugin *plugin, 
-                                      GSignondDictionary *token_data,
-                                      gpointer user_data)
-{    
-    GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (user_data);
-    GSignondPluginProxyPrivate *priv = self->priv;
-
-    if (priv->active_session == NULL) {
-        ERR("Error: plugin %s reported 'store', but no active session \
-            in plugin proxy", priv->plugin_type);
-        return;
-    }
-    gsignond_auth_session_notify_store (priv->active_session, token_data);
-}
-
-static void
-gsignond_plugin_proxy_refreshed_callback (GSignondPlugin *plugin, 
-                                          GSignondSignonuiData *ui_result,
-                                          gpointer user_data)
-{
-    GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (user_data);
-    GSignondPluginProxyPrivate *priv = self->priv;
-
-    if (priv->active_session == NULL) {
-        ERR("Error: plugin %s reported 'refreshed', but no active session \
-            in plugin proxy", priv->plugin_type);
-        return;
-    }
-    gsignond_auth_session_notify_refreshed (priv->active_session, ui_result);
-}
-
-static void
-gsignond_plugin_proxy_user_action_required_callback (
-                                               GSignondPlugin *plugin, 
-                                               GSignondSignonuiData *ui_request, 
-                                               gpointer user_data)
-{
-    GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (user_data);
-    GSignondPluginProxyPrivate *priv = self->priv;
-
-    if (priv->active_session == NULL) {
-        ERR("Error: plugin %s reported 'user_action_required', but no active session \
-            in plugin proxy", priv->plugin_type);
-        return;
-    }
-    gsignond_auth_session_notify_user_action_required(
-        priv->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);
-    GSignondPluginProxyPrivate *priv = self->priv;
-
-    if (priv->active_session == NULL) {
-        ERR("Error: plugin %s reported error %s, but no active session \
-            in plugin proxy", priv->plugin_type, error->message);
-        return;
-    }
-    // This avoids problems if cancel() is called from AuthSession handler
-    GSignondAuthSession *active_session = priv->active_session;
-    priv->active_session = NULL;
-    gsignond_auth_session_notify_process_error (active_session, error, priv->active_process_userdata);
-    g_object_unref (active_session);
-    gsignond_plugin_proxy_process_queue (self);
-}
-
-static void
-gsignond_plugin_proxy_status_changed_callback (GSignondPlugin *plugin, 
-                                               GSignondPluginState state,
-                                               const gchar *message,
-                                               gpointer user_data)
-{
-    GSignondPluginProxy *self = GSIGNOND_PLUGIN_PROXY (user_data);
-    GSignondPluginProxyPrivate *priv = self->priv;
-
-    if (priv->active_session == NULL) {
-        ERR("Error: plugin %s reported change in state %d with message %s, \
-            but no active session in plugin proxy", priv->plugin_type, state,
-            message);
-        return;
-    }
-    gsignond_auth_session_notify_state_changed (priv->active_session,
-                                                (gint) state, message,
-                                                priv->active_process_userdata);
-}
 
index 66ca0bd..03d6fb8 100644 (file)
 #include <gsignond/gsignond-plugin-interface.h>
 #include <gsignond/gsignond-config.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))
-
+#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;
@@ -57,24 +65,32 @@ struct _GSignondPluginProxyClass
     GObjectClass parent_class;
 };
 
-GType gsignond_plugin_proxy_get_type (void);
+GType
+gsignond_plugin_proxy_get_type (void);
 
 GSignondPluginProxy* 
-gsignond_plugin_proxy_new(GSignondConfig *config, const gchar* plugin_type);
-
+gsignond_plugin_proxy_new(
+        GSignondConfig *config,
+        const gchar* plugin_type);
 
 void 
-gsignond_plugin_proxy_cancel (GSignondPluginProxy *self, 
-                        GSignondAuthSession* session);
-void gsignond_plugin_proxy_process (GSignondPluginProxy *self, 
-                              GSignondAuthSession* session,
-                              GSignondSessionData *session_data, 
-                              const gchar *mechanism,
-                              gpointer userdata);
-void gsignond_plugin_proxy_user_action_finished (GSignondPluginProxy *self, 
-                                           GSignondSignonuiData *ui_data);
-void gsignond_plugin_proxy_refresh (GSignondPluginProxy *self, 
-                              GSignondSignonuiData *ui_data);
-
+gsignond_plugin_proxy_cancel (
+        GSignondPluginProxy *self,
+        GSignondAuthSession* session);
+void
+gsignond_plugin_proxy_process (
+        GSignondPluginProxy *self,
+        GSignondAuthSession* session,
+        GSignondSessionData *session_data,
+        const gchar *mechanism,
+        gpointer userdata);
+void
+gsignond_plugin_proxy_user_action_finished (
+        GSignondPluginProxy *self,
+        GSignondSignonuiData *ui_data);
+void
+gsignond_plugin_proxy_refresh (
+        GSignondPluginProxy *self,
+        GSignondSignonuiData *ui_data);
 
 #endif /* __GSIGNOND_PLUGIN_PROXY_H__ */
diff --git a/src/daemon/plugins/gsignond-plugin-remote.c b/src/daemon/plugins/gsignond-plugin-remote.c
new file mode 100644 (file)
index 0000000..3d5c69d
--- /dev/null
@@ -0,0 +1,673 @@
+/* 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) 2013 Intel Corporation.
+ *
+ * Contact: Imran Zaman <imran.zaman@intel.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/gsignond-log.h"
+#include "gsignond/gsignond-error.h"
+#include "gsignond/gsignond-pipe-stream.h"
+#include "gsignond/gsignond-plugin-interface.h"
+#include "daemon/dbus/gsignond-dbus.h"
+#include "gsignond-plugin-remote.h"
+
+enum
+{
+    PROP_0,
+    PROP_TYPE,
+    PROP_MECHANISMS,
+    N_PROPERTIES
+};
+
+//static GParamSpec *properties[N_PROPERTIES];
+
+struct _GSignondPluginRemotePrivate
+{
+    GDBusConnection   *connection;
+    GSignondDbusRemotePlugin *dbus_plugin_proxy;
+    GIOChannel *err_watch_ch;
+    gchar *plugin_type;
+    gchar **plugin_mechanisms;
+    GPid cpid;
+    guint child_watch_id;
+    guint err_watch_id;
+
+    /* Signals */
+    guint signal_response;
+    guint signal_response_final;
+    guint signal_store;
+    guint signal_error;
+    guint signal_user_action_required;
+    guint signal_refreshed;
+    guint signal_status_changed;
+};
+
+static void
+gsignond_plugin_remote_interface_init (
+        GSignondPluginInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GSignondPluginRemote, gsignond_plugin_remote,
+        G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GSIGNOND_TYPE_PLUGIN,
+                gsignond_plugin_remote_interface_init));
+
+#define GSIGNOND_PLUGIN_REMOTE_GET_PRIV(obj) \
+        G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSIGNOND_TYPE_PLUGIN_REMOTE, \
+        GSignondPluginRemotePrivate)
+
+#define GSIGNOND_PLUGIND_NAME "gsignond-plugind"
+
+static void
+gsignond_plugin_remote_set_property (
+        GObject *object,
+        guint property_id,
+        const GValue *value,
+        GParamSpec *pspec)
+{
+    switch (property_id) {
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+gsignond_plugin_remote_get_property (
+        GObject *object,
+        guint property_id,
+        GValue *value, 
+        GParamSpec *pspec)
+{
+    GSignondPluginRemote *self = GSIGNOND_PLUGIN_REMOTE (object);
+
+    switch (property_id) {
+        case PROP_TYPE: {
+            if (!self->priv->plugin_type) {
+                GError *error = NULL;
+                gsignond_dbus_remote_plugin_call_get_info_sync (
+                    self->priv->dbus_plugin_proxy, &self->priv->plugin_type,
+                    &self->priv->plugin_mechanisms, NULL, &error);
+                if (error) {
+                    DBG ("Plugin type retrieval error :: %s", error->message);
+                    g_error_free (error);
+                    self->priv->plugin_type = NULL;
+                }
+            }
+            g_value_set_string (value, self->priv->plugin_type);
+            break;
+        }
+        case PROP_MECHANISMS: {
+            if (!self->priv->plugin_mechanisms) {
+                GError *error = NULL;
+                gsignond_dbus_remote_plugin_call_get_info_sync (
+                    self->priv->dbus_plugin_proxy, &self->priv->plugin_type,
+                    &self->priv->plugin_mechanisms, NULL, &error);
+                if (error) {
+                    DBG ("Plugin mechanisms retrieval error :: %s",
+                            error->message);
+                    g_error_free (error);
+                    self->priv->plugin_mechanisms = NULL;
+                }
+            }
+            g_value_set_boxed (value, self->priv->plugin_mechanisms);
+            break;
+        }
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+
+}
+
+static void
+gsignond_plugin_remote_dispose (GObject *object)
+{
+    GSignondPluginRemote *self = GSIGNOND_PLUGIN_REMOTE (object);
+
+    if (self->priv->err_watch_ch) {
+        g_io_channel_shutdown (self->priv->err_watch_ch, FALSE, NULL);
+        g_io_channel_unref (self->priv->err_watch_ch);
+        g_source_remove (self->priv->err_watch_id);
+        self->priv->err_watch_ch = NULL;
+    }
+
+    if (self->priv->connection) {
+        g_object_unref (self->priv->connection);
+        self->priv->connection = NULL;
+    }
+
+    if (self->priv->dbus_plugin_proxy) {
+        g_signal_handler_disconnect (self->priv->dbus_plugin_proxy,
+                self->priv->signal_response);
+        g_signal_handler_disconnect (self->priv->dbus_plugin_proxy,
+                self->priv->signal_response_final);
+        g_signal_handler_disconnect (self->priv->dbus_plugin_proxy,
+                self->priv->signal_store);
+        g_signal_handler_disconnect (self->priv->dbus_plugin_proxy,
+                self->priv->signal_error);
+        g_signal_handler_disconnect (self->priv->dbus_plugin_proxy,
+                self->priv->signal_user_action_required);
+        g_signal_handler_disconnect (self->priv->dbus_plugin_proxy,
+                self->priv->signal_refreshed);
+        g_signal_handler_disconnect (self->priv->dbus_plugin_proxy,
+                self->priv->signal_status_changed);
+        g_object_unref (self->priv->dbus_plugin_proxy);
+        self->priv->dbus_plugin_proxy = NULL;
+    }
+
+    if (self->priv->cpid > 0) {
+        if (self->priv->child_watch_id) {
+            g_source_remove (self->priv->child_watch_id);
+            self->priv->child_watch_id = 0;
+        }
+        kill (self->priv->cpid, SIGTERM);
+        self->priv->cpid = 0;
+    }
+
+    G_OBJECT_CLASS (gsignond_plugin_remote_parent_class)->dispose (object);
+}
+
+static void
+gsignond_plugin_remote_finalize (GObject *object)
+{
+    GSignondPluginRemote *self = GSIGNOND_PLUGIN_REMOTE (object);
+
+    if (self->priv->plugin_type) {
+        g_free (self->priv->plugin_type);
+        self->priv->plugin_type = NULL;
+    }
+
+    if (self->priv->plugin_mechanisms) {
+        g_strfreev (self->priv->plugin_mechanisms);
+        self->priv->plugin_mechanisms = NULL;
+    }
+
+    G_OBJECT_CLASS (gsignond_plugin_remote_parent_class)->finalize (object);
+}
+
+static void
+gsignond_plugin_remote_class_init (GSignondPluginRemoteClass *klass)
+{
+    GObjectClass* object_class = G_OBJECT_CLASS (klass);
+
+    g_type_class_add_private (object_class,
+            sizeof (GSignondPluginRemotePrivate));
+
+    object_class->get_property = gsignond_plugin_remote_get_property;
+    object_class->set_property = gsignond_plugin_remote_set_property;
+    object_class->dispose = gsignond_plugin_remote_dispose;
+    object_class->finalize = gsignond_plugin_remote_finalize;
+
+    g_object_class_override_property (object_class, PROP_TYPE, "type");
+    g_object_class_override_property (object_class, PROP_MECHANISMS,
+            "mechanisms");
+
+}
+
+/* signals */
+enum
+{
+    USER_ACTION_FINISHED_TRIGGERED,
+    LAST_SIGNAL
+};
+static guint task_signals[LAST_SIGNAL] = { 0 };
+
+static void
+gsignond_plugin_remote_init (GSignondPluginRemote *self)
+{
+    self->priv = GSIGNOND_PLUGIN_REMOTE_GET_PRIV(self);
+
+    self->priv->connection = NULL;
+    self->priv->dbus_plugin_proxy = NULL;
+    self->priv->err_watch_ch = NULL;
+    self->priv->plugin_type = NULL;
+    self->priv->plugin_mechanisms = NULL;
+    self->priv->cpid = 0;
+    self->priv->child_watch_id = 0;
+
+}
+
+static void
+_cancel_async_cb (
+        GObject *object,
+        GAsyncResult *res,
+        gpointer user_data)
+{
+    GError *error = NULL;
+    GSignondDbusRemotePlugin *proxy = GSIGNOND_DBUS_REMOTE_PLUGIN (object);
+    GSignondPluginRemote *self = GSIGNOND_PLUGIN_REMOTE (user_data);
+
+    gsignond_dbus_remote_plugin_call_cancel_finish (proxy, res, &error);
+    if (error) {
+        gsignond_plugin_error (GSIGNOND_PLUGIN(self), error);
+        g_error_free (error);
+    }
+}
+
+static void
+gsignond_plugin_remote_cancel (
+        GSignondPlugin *plugin)
+{
+    g_return_if_fail (plugin && GSIGNOND_IS_PLUGIN_REMOTE (plugin));
+    GSignondPluginRemote *self = GSIGNOND_PLUGIN_REMOTE (plugin);
+
+    gsignond_dbus_remote_plugin_call_cancel (
+            self->priv->dbus_plugin_proxy, NULL, _cancel_async_cb, self);
+}
+
+static void
+_request_initial_async_cb (
+        GObject *object,
+        GAsyncResult *res,
+        gpointer user_data)
+{
+    GError *error = NULL;
+    GSignondDbusRemotePlugin *proxy = GSIGNOND_DBUS_REMOTE_PLUGIN (object);
+    GSignondPluginRemote *self = GSIGNOND_PLUGIN_REMOTE (user_data);
+    gsignond_dbus_remote_plugin_call_request_initial_finish (proxy,
+            res, &error);
+    if (error) {
+        gsignond_plugin_error (GSIGNOND_PLUGIN(self), error);
+        g_error_free (error);
+    }
+}
+
+static void
+gsignond_plugin_remote_request_initial (
+    GSignondPlugin *plugin,
+    GSignondSessionData *session_data,
+    const gchar *mechanism)
+{
+    g_return_if_fail (session_data && plugin &&
+            GSIGNOND_IS_PLUGIN_REMOTE (plugin));
+    GSignondPluginRemote *self = GSIGNOND_PLUGIN_REMOTE (plugin);
+
+    GVariant *data = gsignond_dictionary_to_variant (session_data);
+    gsignond_dbus_remote_plugin_call_request_initial (
+            self->priv->dbus_plugin_proxy, data, mechanism, NULL,
+            _request_initial_async_cb, self);
+}
+
+static void
+_request_async_cb (
+        GObject *object,
+        GAsyncResult *res,
+        gpointer user_data)
+{
+    GError *error = NULL;
+    GSignondDbusRemotePlugin *proxy = GSIGNOND_DBUS_REMOTE_PLUGIN (object);
+    GSignondPluginRemote *self = GSIGNOND_PLUGIN_REMOTE (user_data);
+
+    gsignond_dbus_remote_plugin_call_request_finish (proxy, res, &error);
+    if (error) {
+        gsignond_plugin_error (GSIGNOND_PLUGIN(self), error);
+        g_error_free (error);
+    }
+}
+
+static void
+gsignond_plugin_remote_request (
+    GSignondPlugin *plugin,
+    GSignondSessionData *session_data)
+{
+    g_return_if_fail (session_data && plugin &&
+            GSIGNOND_IS_PLUGIN_REMOTE (plugin));
+    GSignondPluginRemote *self = GSIGNOND_PLUGIN_REMOTE (plugin);
+
+    GVariant *data = gsignond_dictionary_to_variant (session_data);
+    gsignond_dbus_remote_plugin_call_request (
+            self->priv->dbus_plugin_proxy, data, NULL, _request_async_cb, self);
+}
+
+static void
+_user_action_finished_async_cb (
+        GObject *object,
+        GAsyncResult *res,
+        gpointer user_data)
+{
+    GError *error = NULL;
+    GSignondDbusRemotePlugin *proxy = GSIGNOND_DBUS_REMOTE_PLUGIN (object);
+    GSignondPluginRemote *self = GSIGNOND_PLUGIN_REMOTE (user_data);
+
+    gsignond_dbus_remote_plugin_call_user_action_finished_finish (proxy,
+            res, &error);
+    if (error) {
+        gsignond_plugin_error (GSIGNOND_PLUGIN(self), error);
+        g_error_free (error);
+    } else {
+        g_signal_emit (self, task_signals[USER_ACTION_FINISHED_TRIGGERED], 0);
+    }
+}
+
+static void
+gsignond_plugin_remote_user_action_finished (
+    GSignondPlugin *plugin,
+    GSignondSignonuiData *signonui_data)
+{
+    g_return_if_fail (signonui_data && plugin &&
+            GSIGNOND_IS_PLUGIN_REMOTE (plugin));
+    GSignondPluginRemote *self = GSIGNOND_PLUGIN_REMOTE (plugin);
+
+    GVariant *data = gsignond_signonui_data_to_variant (signonui_data);
+    gsignond_dbus_remote_plugin_call_user_action_finished (
+            self->priv->dbus_plugin_proxy, data, NULL,
+            _user_action_finished_async_cb, self);
+}
+
+static void
+_refresh_async_cb (
+        GObject *object,
+        GAsyncResult *res,
+        gpointer user_data)
+{
+    GError *error = NULL;
+    GSignondDbusRemotePlugin *proxy = GSIGNOND_DBUS_REMOTE_PLUGIN (object);
+    GSignondPluginRemote *self = GSIGNOND_PLUGIN_REMOTE (user_data);
+
+    gsignond_dbus_remote_plugin_call_refresh_finish (proxy, res, &error);
+    if (error) {
+        gsignond_plugin_error (GSIGNOND_PLUGIN(self), error);
+        g_error_free (error);
+    }
+}
+
+static void
+gsignond_plugin_remote_refresh (
+    GSignondPlugin *plugin,
+    GSignondSignonuiData *signonui_data)
+{
+    g_return_if_fail (signonui_data && plugin &&
+            GSIGNOND_IS_PLUGIN_REMOTE (plugin));
+    GSignondPluginRemote *self = GSIGNOND_PLUGIN_REMOTE (plugin);
+
+    GVariant *data = gsignond_signonui_data_to_variant (signonui_data);
+    gsignond_dbus_remote_plugin_call_refresh (
+            self->priv->dbus_plugin_proxy, data, NULL, _refresh_async_cb, self);
+}
+
+static void
+gsignond_plugin_remote_interface_init (GSignondPluginInterface *iface)
+{
+    iface->cancel = gsignond_plugin_remote_cancel;
+    iface->request_initial = gsignond_plugin_remote_request_initial;
+    iface->request = gsignond_plugin_remote_request;
+    iface->user_action_finished = gsignond_plugin_remote_user_action_finished;
+    iface->refresh = gsignond_plugin_remote_refresh;
+
+    task_signals[USER_ACTION_FINISHED_TRIGGERED] = g_signal_new (
+            "user-action-finished-triggered", G_TYPE_FROM_CLASS (iface),
+            G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
+}
+
+static void
+_response_cb (
+        GSignondPluginRemote *self,
+        GVariant *session_data,
+        gpointer user_data)
+{
+    g_return_if_fail (self && GSIGNOND_IS_PLUGIN_REMOTE (self));
+
+    GSignondSessionData *data = (GSignondSessionData *)
+            gsignond_dictionary_new_from_variant (session_data);
+    gsignond_plugin_response (GSIGNOND_PLUGIN(self), data);
+    gsignond_dictionary_unref (data);
+}
+
+static void
+_response_final_cb (
+        GSignondPluginRemote *self,
+        GVariant *session_data,
+        gpointer user_data)
+{
+    g_return_if_fail (self && GSIGNOND_IS_PLUGIN_REMOTE (self));
+
+    GSignondSessionData *data = (GSignondSessionData *)
+            gsignond_dictionary_new_from_variant (session_data);
+    gsignond_plugin_response_final (GSIGNOND_PLUGIN(self), data);
+    gsignond_dictionary_unref (data);
+}
+
+static void
+_store_cb (
+        GSignondPluginRemote *self,
+        GVariant *session_data,
+        gpointer user_data)
+{
+    g_return_if_fail (self && GSIGNOND_IS_PLUGIN_REMOTE (self));
+
+    GSignondSessionData *data = (GSignondSessionData *)
+            gsignond_dictionary_new_from_variant (session_data);
+    gsignond_plugin_store (GSIGNOND_PLUGIN(self), data);
+    gsignond_dictionary_unref (data);
+}
+
+static void
+_error_cb (
+        GSignondPluginRemote *self,
+        GVariant *error,
+        gpointer user_data)
+{
+    g_return_if_fail (self && GSIGNOND_IS_PLUGIN_REMOTE (self));
+    GError *gerror = gsignond_error_new_from_variant (error);
+    gsignond_plugin_error (GSIGNOND_PLUGIN(self), gerror);
+    g_error_free (gerror);
+}
+
+static void
+_user_action_required_cb (
+        GSignondPluginRemote *self,
+        GVariant *ui_data,
+        gpointer user_data)
+{
+    g_return_if_fail (self && GSIGNOND_IS_PLUGIN_REMOTE (self));
+
+    GSignondSignonuiData *data = (GSignondSignonuiData *)
+            gsignond_signonui_data_new_from_variant (ui_data);
+    gsignond_plugin_user_action_required (GSIGNOND_PLUGIN(self), data);
+    gsignond_signonui_data_unref (data);
+}
+
+static void
+_refreshed_cb(
+        GSignondPluginRemote *self,
+        GVariant *ui_data,
+        gpointer user_data)
+{
+    g_return_if_fail (self && GSIGNOND_IS_PLUGIN_REMOTE (self));
+
+    GSignondSignonuiData *data = (GSignondSignonuiData *)
+            gsignond_signonui_data_new_from_variant (ui_data);
+    gsignond_plugin_refreshed (GSIGNOND_PLUGIN(self), data);
+    gsignond_signonui_data_unref (data);
+}
+
+static void
+_status_changed_cb (
+        GSignondPluginRemote *self,
+        gint status,
+        gchar *message,
+        gpointer user_data)
+{
+    g_return_if_fail (self && GSIGNOND_IS_PLUGIN_REMOTE (self));
+
+    gsignond_plugin_status_changed (GSIGNOND_PLUGIN(self),
+            (GSignondPluginState)status, message);
+}
+
+static gboolean
+_error_watch_cb (
+        GIOChannel *channel,
+        GIOCondition condition,
+        gpointer data)
+{
+
+    GSignondPluginRemote *plugin = (GSignondPluginRemote*)data;
+
+    if (condition == G_IO_HUP || condition == G_IO_ERR ||
+            condition == G_IO_NVAL) {
+        g_io_channel_shutdown (plugin->priv->err_watch_ch, FALSE, NULL);
+        g_io_channel_unref (plugin->priv->err_watch_ch);
+        plugin->priv->err_watch_ch = NULL;
+        g_source_remove (plugin->priv->err_watch_id);
+        DBG ("Plugind (%s) is down",
+                plugin->priv->plugin_type ? plugin->priv->plugin_type : "");
+        return FALSE;
+    }
+
+    if (g_io_channel_get_flags (channel) & G_IO_FLAG_IS_READABLE) {
+        gchar * string = NULL;
+        GError *error = NULL;
+        gsize bytes_read = 0;
+        gboolean keep_error_source = TRUE;
+        GIOStatus status = g_io_channel_read_line (channel, &string,
+                &bytes_read, NULL, &error);
+        if (status == G_IO_STATUS_NORMAL && bytes_read > 0 && error == NULL) {
+            DBG ("(%s) %s",plugin->priv?(plugin->priv->plugin_type ?
+                    plugin->priv->plugin_type : "NULL"):"NULL", string);
+        }
+        if (string) {
+            g_free (string);
+        }
+        keep_error_source = (bytes_read > 0 && error == NULL);
+        if (error) {
+            g_error_free (error);
+        }
+        if (!keep_error_source) {
+            DBG ("Removing error source- bytes_read %d, error %p",
+                    (gint)bytes_read, error?error:NULL);
+        }
+        return keep_error_source;
+    }
+
+    return TRUE;
+}
+
+static void
+_child_watch_cb (
+        GPid  pid,
+        gint  status,
+        gpointer data)
+{
+    GSignondPluginRemote *plugin = (GSignondPluginRemote*)data;
+    DBG ("Plugin process (%s) with pid (%d) closed",
+            plugin->priv->plugin_type ? plugin->priv->plugin_type : "", pid);
+    g_spawn_close_pid (pid);
+    g_source_remove (plugin->priv->child_watch_id);
+    plugin->priv->child_watch_id = 0;
+}
+
+GSignondPluginRemote *
+gsignond_plugin_remote_new (
+        GSignondConfig *config,
+        const gchar *plugin_type)
+{
+    gchar *object_path = NULL;
+    GError *error = NULL;
+    GPid cpid = 0;
+    gchar **argv;
+    gint cin_fd, cout_fd, cerr_fd;
+    GSignondPluginRemote *plugin = NULL;
+    GSignondPipeStream *stream = NULL;
+    gboolean ret = FALSE;
+
+    /* Spawn child process */
+    argv = g_malloc0 ((3 + 1) * sizeof (gchar *));
+    argv[0] = g_build_filename (gsignond_config_get_string (config,
+            GSIGNOND_CONFIG_GENERAL_BIN_DIR), GSIGNOND_PLUGIND_NAME, NULL);
+    argv[1] = g_module_build_path (gsignond_config_get_string (config,
+            GSIGNOND_CONFIG_GENERAL_PLUGINS_DIR), plugin_type);
+    argv[2] = g_strdup(plugin_type);
+    ret = g_spawn_async_with_pipes (NULL, argv, NULL,
+            G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL,
+            NULL, &cpid, &cin_fd, &cout_fd, &cerr_fd, &error);
+    g_strfreev (argv);
+    if (ret == FALSE || (kill(cpid, 0) != 0)) {
+        DBG ("failed to start plugind: ret(%d)", ret);
+        if (error) g_error_free (error);
+        return NULL;
+    }
+    /* Create dbus plugin object */
+    plugin = GSIGNOND_PLUGIN_REMOTE (g_object_new (GSIGNOND_TYPE_PLUGIN_REMOTE,
+            NULL));
+
+    plugin->priv->child_watch_id = g_child_watch_add (cpid,
+            (GChildWatchFunc)_child_watch_cb, plugin);
+    plugin->priv->cpid = cpid;
+
+    object_path = g_strdup_printf ("%s_%s", GSIGNOND_PLUGIN_OBJECTPATH,
+            plugin_type);
+
+    /* Create dbus connection */
+    stream = gsignond_pipe_stream_new (cout_fd, cin_fd);
+    plugin->priv->connection = g_dbus_connection_new_sync (G_IO_STREAM (stream),
+            NULL, G_DBUS_CONNECTION_FLAGS_NONE, NULL, NULL, NULL);
+    g_object_unref (stream);
+
+    /* Create dbus proxy */
+    plugin->priv->dbus_plugin_proxy =
+            gsignond_dbus_remote_plugin_proxy_new_sync (
+                    plugin->priv->connection,
+                    G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+                    NULL,
+                    object_path,
+                    NULL,
+                    &error);
+    if (error) {
+        DBG ("Failed to register object: %s", error->message);
+        g_error_free (error);
+        g_free (object_path);
+        g_object_unref (plugin);
+        return NULL;
+    }
+    DBG("'%s' object exported(%p)", object_path, plugin);
+    g_free (object_path);
+
+    plugin->priv->signal_response = g_signal_connect_swapped (
+            plugin->priv->dbus_plugin_proxy, "response",
+            G_CALLBACK (_response_cb), plugin);
+    plugin->priv->signal_response_final = g_signal_connect_swapped (
+            plugin->priv->dbus_plugin_proxy, "response-final",
+            G_CALLBACK(_response_final_cb), plugin);
+    plugin->priv->signal_store = g_signal_connect_swapped (
+            plugin->priv->dbus_plugin_proxy, "store",
+            G_CALLBACK(_store_cb), plugin);
+    plugin->priv->signal_error = g_signal_connect_swapped (
+            plugin->priv->dbus_plugin_proxy, "error",
+            G_CALLBACK(_error_cb), plugin);
+    plugin->priv->signal_user_action_required = g_signal_connect_swapped (
+            plugin->priv->dbus_plugin_proxy, "user-action-required",
+            G_CALLBACK(_user_action_required_cb), plugin);
+    plugin->priv->signal_refreshed = g_signal_connect_swapped (
+            plugin->priv->dbus_plugin_proxy, "refreshed",
+            G_CALLBACK(_refreshed_cb), plugin);
+    plugin->priv->signal_status_changed = g_signal_connect_swapped (
+            plugin->priv->dbus_plugin_proxy, "status-changed",
+            G_CALLBACK(_status_changed_cb), plugin);
+
+    /* Create watch for error messages */
+    plugin->priv->err_watch_ch = g_io_channel_unix_new (cerr_fd);
+    plugin->priv->err_watch_id = g_io_add_watch (plugin->priv->err_watch_ch,
+            G_IO_IN | G_IO_HUP, (GIOFunc)_error_watch_cb, plugin);
+    g_io_channel_set_close_on_unref (plugin->priv->err_watch_ch, TRUE);
+    g_io_channel_set_flags (plugin->priv->err_watch_ch, G_IO_FLAG_NONBLOCK,
+            NULL);
+
+    return plugin;
+}
+
diff --git a/src/daemon/plugins/gsignond-plugin-remote.h b/src/daemon/plugins/gsignond-plugin-remote.h
new file mode 100644 (file)
index 0000000..59807d8
--- /dev/null
@@ -0,0 +1,77 @@
+/* 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) 2013 Intel Corporation.
+ *
+ * Contact: Imran Zaman <imran.zaman@intel.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_REMOTE_H_
+#define __GSIGNOND_PLUGIN_REMOTE_H_
+
+#include <glib.h>
+#include <daemon/dbus/gsignond-dbus-remote-plugin-gen.h>
+#include <gsignond/gsignond-config.h>
+
+G_BEGIN_DECLS
+
+#define GSIGNOND_TYPE_PLUGIN_REMOTE \
+    (gsignond_plugin_remote_get_type())
+#define GSIGNOND_PLUGIN_REMOTE(obj)  (G_TYPE_CHECK_INSTANCE_CAST((obj),\
+    GSIGNOND_TYPE_PLUGIN_REMOTE, GSignondPluginRemote))
+#define GSIGNOND_PLUGIN_REMOTE_CLASS(klass)\
+    (G_TYPE_CHECK_CLASS_CAST((klass), GSIGNOND_TYPE_PLUGIN_REMOTE, \
+    GSignondPluginRemoteClass))
+#define GSIGNOND_IS_PLUGIN_REMOTE(obj)         \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GSIGNOND_TYPE_PLUGIN_REMOTE))
+#define GSIGNOND_IS_PLUGIN_REMOTE_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GSIGNOND_TYPE_PLUGIN_REMOTE))
+#define GSIGNOND_PLUGIN_REMOTE_GET_CLASS(obj)  \
+    (G_TYPE_INSTANCE_GET_CLASS((obj), GSIGNOND_TYPE_PLUGIN_REMOTE, \
+    GSignondPluginRemoteClass))
+
+typedef struct _GSignondPluginRemote GSignondPluginRemote;
+typedef struct _GSignondPluginRemoteClass GSignondPluginRemoteClass;
+typedef struct _GSignondPluginRemotePrivate GSignondPluginRemotePrivate;
+
+struct _GSignondPluginRemote
+{
+    GObject parent;
+
+    /* priv */
+    GSignondPluginRemotePrivate *priv;
+};
+
+struct _GSignondPluginRemoteClass
+{
+    GObjectClass parent_class;
+};
+
+GType
+gsignond_plugin_remote_get_type (void) G_GNUC_CONST;
+
+GSignondPluginRemote *
+gsignond_plugin_remote_new (
+        GSignondConfig *config,
+        const gchar *plugin_type);
+
+G_END_DECLS
+
+#endif /* __GSIGNOND_PLUGIN_REMOTE_H_ */
diff --git a/src/daemon/plugins/plugind/Makefile.am b/src/daemon/plugins/plugind/Makefile.am
new file mode 100644 (file)
index 0000000..d4ca2eb
--- /dev/null
@@ -0,0 +1,23 @@
+SUBDIRS=
+NULL=
+
+bin_PROGRAMS = gsignond-plugind
+
+gsignond_plugind_SOURCES = \
+    main.c \
+    gsignond-plugin-daemon.c \
+    $(NULL)
+
+gsignond_plugind_CFLAGS = \
+    -I$(top_srcdir) \
+    -I$(top_srcdir)/include/ \
+    -I$(top_srcdir)/src/ \
+    $(GSIGNOND_CFLAGS) \
+    $(NULL)
+
+gsignond_plugind_LDADD = \
+    $(top_srcdir)/src/common/libgsignond-common.la \
+    $(top_srcdir)/src/daemon/dbus/libgsignond-dbus-glue.la \
+    $(GSIGNOND_LIBS) \
+    $(NULL)
+
diff --git a/src/daemon/plugins/plugind/gsignond-plugin-daemon.c b/src/daemon/plugins/plugind/gsignond-plugin-daemon.c
new file mode 100644 (file)
index 0000000..6cb8cea
--- /dev/null
@@ -0,0 +1,446 @@
+/* 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) 2013 Intel Corporation.
+ *
+ * Contact: Imran Zaman <imran.zaman@intel.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/gsignond-plugin-interface.h"
+#include "daemon/dbus/gsignond-dbus-remote-plugin-gen.h"
+#include "daemon/dbus/gsignond-dbus.h"
+#include "gsignond/gsignond-plugin-loader.h"
+#include "gsignond/gsignond-pipe-stream.h"
+#include "gsignond/gsignond-log.h"
+#include "gsignond/gsignond-error.h"
+#include "gsignond-plugin-daemon.h"
+
+struct _GSignondPluginDaemonPrivate
+{
+    GDBusConnection   *connection;
+    GSignondDbusRemotePlugin *dbus_remote_plugin;
+    GSignondPlugin *plugin;
+    gchar *plugin_type;
+};
+
+G_DEFINE_TYPE (GSignondPluginDaemon, gsignond_plugin_daemon, G_TYPE_OBJECT)
+
+
+#define GSIGNOND_PLUGIN_DAEMON_GET_PRIV(obj) \
+    G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSIGNOND_TYPE_PLUGIN_DAEMON,\
+            GSignondPluginDaemonPrivate)
+
+static void
+_dispose (GObject *object)
+{
+    GSignondPluginDaemon *self = GSIGNOND_PLUGIN_DAEMON (object);
+
+    if (self->priv->dbus_remote_plugin) {
+        g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (
+                self->priv->dbus_remote_plugin));
+        g_object_unref (self->priv->dbus_remote_plugin);
+        self->priv->dbus_remote_plugin = NULL;
+    }
+
+    if (self->priv->connection) {
+        g_object_unref (self->priv->connection);
+        self->priv->connection = NULL;
+    }
+
+    if (self->priv->plugin) {
+        g_object_unref (self->priv->plugin);
+        self->priv->plugin = NULL;
+    }
+
+    G_OBJECT_CLASS (gsignond_plugin_daemon_parent_class)->dispose (object);
+}
+
+static void
+_finalize (GObject *object)
+{
+    GSignondPluginDaemon *self = GSIGNOND_PLUGIN_DAEMON (object);
+
+    if (self->priv->plugin_type) {
+        g_free (self->priv->plugin_type);
+        self->priv->plugin_type = NULL;
+    }
+
+    G_OBJECT_CLASS (gsignond_plugin_daemon_parent_class)->finalize (object);
+}
+
+static void
+gsignond_plugin_daemon_class_init (
+        GSignondPluginDaemonClass *klass)
+{
+    GObjectClass* object_class = G_OBJECT_CLASS (klass);
+
+    g_type_class_add_private (object_class, sizeof (
+            GSignondPluginDaemonPrivate));
+
+    object_class->dispose = _dispose;
+    object_class->finalize = _finalize;
+
+}
+
+static void
+gsignond_plugin_daemon_init (
+        GSignondPluginDaemon *self)
+{
+    self->priv = GSIGNOND_PLUGIN_DAEMON_GET_PRIV(self);
+    self->priv->connection = NULL;
+    self->priv->dbus_remote_plugin = NULL;
+    self->priv->plugin_type = NULL;
+    self->priv->plugin = NULL;
+}
+
+static void
+_on_connection_closed (
+        GDBusConnection *connection,
+        gboolean         remote_peer_vanished,
+        GError          *error,
+        gpointer         user_data)
+{
+    GSignondPluginDaemon *daemon = GSIGNOND_PLUGIN_DAEMON (user_data);
+
+    g_signal_handlers_disconnect_by_func (connection, _on_connection_closed,
+            user_data);
+    DBG("dbus connection(%p) closed (peer vanished : %d)", connection,
+            remote_peer_vanished);
+    if (error) {
+       DBG("...reason : %s", error->message);
+    }
+    g_object_unref (daemon);
+}
+
+static gboolean
+_handle_cancel_from_dbus (
+        GSignondPluginDaemon *self,
+        GDBusMethodInvocation *invocation,
+        gpointer user_data)
+{
+    DBG ("");
+    g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
+    gsignond_dbus_remote_plugin_complete_cancel (self->priv->dbus_remote_plugin,
+            invocation);
+
+    gsignond_plugin_cancel (self->priv->plugin);
+    return TRUE;
+}
+
+static gboolean
+_handle_request_from_dbus (
+        GSignondPluginDaemon *self,
+        GDBusMethodInvocation *invocation,
+        const GVariant *session_data,
+        gpointer user_data)
+{
+    DBG ("");
+    g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
+
+    gsignond_dbus_remote_plugin_complete_request (
+            self->priv->dbus_remote_plugin, invocation);
+
+    GSignondSessionData *data = (GSignondSessionData *)
+            gsignond_dictionary_new_from_variant ((GVariant *)session_data);
+    gsignond_plugin_request (self->priv->plugin, data);
+    gsignond_dictionary_unref (data);
+    return TRUE;
+}
+
+static void
+_handle_response_final_from_plugin (
+        GSignondPluginDaemon *self,
+        GSignondSessionData *session_data,
+        gpointer user_data);
+
+static gboolean
+_handle_request_initial_from_dbus (
+        GSignondPluginDaemon *self,
+        GDBusMethodInvocation *invocation,
+        const GVariant *session_data,
+        const gchar *mechanism,
+        gpointer user_data)
+{
+    DBG ("");
+    g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
+
+    gsignond_dbus_remote_plugin_complete_request_initial (
+            self->priv->dbus_remote_plugin, invocation);
+
+    GSignondSessionData *data = (GSignondSessionData *)
+            gsignond_dictionary_new_from_variant ((GVariant *)session_data);
+    gsignond_plugin_request_initial (self->priv->plugin, data, mechanism);
+    gsignond_dictionary_unref (data);
+
+    return TRUE;
+}
+
+static gboolean
+_handle_user_action_finished_from_dbus (
+        GSignondPluginDaemon *self,
+        GDBusMethodInvocation *invocation,
+        const GVariant *ui_data,
+        gpointer user_data)
+{
+    DBG ("");
+    g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
+
+    gsignond_dbus_remote_plugin_complete_user_action_finished (
+            self->priv->dbus_remote_plugin, invocation);
+
+    GSignondSignonuiData *data = (GSignondSignonuiData *)
+            gsignond_signonui_data_new_from_variant ((GVariant *)ui_data);
+    gsignond_plugin_user_action_finished (self->priv->plugin, data);
+    gsignond_signonui_data_unref (data);
+    return TRUE;
+}
+
+static gboolean
+_handle_refresh_from_dbus (
+        GSignondPluginDaemon *self,
+        GDBusMethodInvocation *invocation,
+        const GVariant *ui_data,
+        gpointer user_data)
+{
+    DBG ("");
+    g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
+
+    gsignond_dbus_remote_plugin_complete_refresh (
+            self->priv->dbus_remote_plugin, invocation);
+
+    GSignondSignonuiData *data = (GSignondSignonuiData *)
+            gsignond_signonui_data_new_from_variant ((GVariant *)ui_data);
+    gsignond_plugin_refresh (self->priv->plugin, data);
+    gsignond_signonui_data_unref (data);
+    return TRUE;
+}
+
+static gboolean
+_handle_get_info_from_dbus (
+        GSignondPluginDaemon *self,
+        GDBusMethodInvocation *invocation,
+        gpointer user_data)
+{
+    DBG ("");
+    g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
+    gchar *type = NULL;
+    gchar **mechanisms = NULL;
+
+    g_object_get (self->priv->plugin, "type", &type, "mechanisms", &mechanisms,
+            NULL);
+    gsignond_dbus_remote_plugin_complete_get_info (
+            self->priv->dbus_remote_plugin, invocation, (const gchar*)type,
+            (const gchar *const *)mechanisms);
+    g_free (type);
+    g_strfreev (mechanisms);
+    return TRUE;
+}
+
+static void
+_handle_response_from_plugin (
+        GSignondPluginDaemon *self,
+        GSignondSessionData *session_data,
+        gpointer user_data)
+{
+    DBG ("");
+    g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
+
+    GVariant *data = gsignond_dictionary_to_variant (
+            (GSignondDictionary *)session_data);
+    gsignond_dbus_remote_plugin_emit_response (self->priv->dbus_remote_plugin,
+            data);
+}
+
+static void
+_handle_response_final_from_plugin (
+        GSignondPluginDaemon *self,
+        GSignondSessionData *session_data,
+        gpointer user_data)
+{
+    DBG ("");
+    g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
+
+    GVariant *data = gsignond_dictionary_to_variant (
+            (GSignondDictionary *)session_data);
+    gsignond_dbus_remote_plugin_emit_response_final (
+            self->priv->dbus_remote_plugin, data);
+}
+
+static void
+_handle_store_from_plugin (
+        GSignondPluginDaemon *self,
+        GSignondSessionData *session_data,
+        gpointer user_data)
+{
+    DBG ("");
+    g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
+
+    GVariant *data = gsignond_dictionary_to_variant (
+            (GSignondDictionary *)session_data);
+    gsignond_dbus_remote_plugin_emit_store (self->priv->dbus_remote_plugin,
+            data);
+}
+
+static void
+_handle_error_from_plugin (
+        GSignondPluginDaemon *self,
+        GError *gerror,
+        gpointer user_data)
+{
+    DBG ("");
+    g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
+
+    GVariant *error = gsignond_error_to_variant (gerror);
+    gsignond_dbus_remote_plugin_emit_error (self->priv->dbus_remote_plugin,
+            error);
+}
+
+static void
+_handle_user_action_required_from_plugin (
+        GSignondPluginDaemon *self,
+        GSignondSignonuiData *ui_data,
+        gpointer user_data)
+{
+    DBG ("");
+    g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
+
+    GVariant *data = gsignond_signonui_data_to_variant (ui_data);
+    gsignond_dbus_remote_plugin_emit_user_action_required (
+            self->priv->dbus_remote_plugin, data);
+}
+
+static void
+_handle_refreshed_from_plugin(
+        GSignondPluginDaemon *self,
+        GSignondSignonuiData *ui_data,
+        gpointer user_data)
+{
+    DBG ("");
+    g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
+
+    GVariant *data = gsignond_signonui_data_to_variant (ui_data);
+    gsignond_dbus_remote_plugin_emit_refreshed (self->priv->dbus_remote_plugin,
+            data);
+}
+
+static void
+_handle_status_changed_from_plugin (
+        GSignondPluginDaemon *self,
+        GSignondPluginState status,
+        gchar *message,
+        gpointer user_data)
+{
+    DBG ("");
+    g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
+
+    gsignond_dbus_remote_plugin_emit_status_changed (
+            self->priv->dbus_remote_plugin, (gint)status,
+            (const gchar *)message);
+}
+
+GSignondPluginDaemon *
+gsignond_plugin_daemon_new (
+        const gchar* filename,
+        const gchar* plugin_type)
+{
+    GError *error = NULL;
+    gchar *object_path = NULL;
+    GSignondPipeStream *stream = NULL;
+
+    g_return_val_if_fail (filename != NULL && plugin_type != NULL, NULL);
+
+    GSignondPluginDaemon *daemon = GSIGNOND_PLUGIN_DAEMON (g_object_new (
+            GSIGNOND_TYPE_PLUGIN_DAEMON, NULL));
+
+    /* Load plugin */
+    daemon->priv->plugin = gsignond_load_plugin_with_filename (
+            (gchar *)plugin_type, (gchar *)filename);
+    if (!daemon->priv->plugin) {
+        DBG ("failed to load plugin");
+        g_object_unref (daemon);
+        return NULL;
+    }
+
+    daemon->priv->plugin_type = g_strdup (plugin_type);
+
+    /* Create dbus connection */
+    stream = gsignond_pipe_stream_new (0, 1);
+    daemon->priv->connection = g_dbus_connection_new_sync (G_IO_STREAM (stream),
+            NULL, G_DBUS_CONNECTION_FLAGS_NONE, NULL, NULL, NULL);
+    g_object_unref (stream);
+
+    /* Create dbus object */
+    daemon->priv->dbus_remote_plugin =
+            gsignond_dbus_remote_plugin_skeleton_new ();
+
+    object_path = g_strdup_printf ("%s_%s", GSIGNOND_PLUGIN_OBJECTPATH,
+            daemon->priv->plugin_type);
+    g_dbus_interface_skeleton_export (
+                G_DBUS_INTERFACE_SKELETON(daemon->priv->dbus_remote_plugin),
+                daemon->priv->connection, object_path, &error);
+    if (error) {
+        DBG ("failed to register object: %s", error->message);
+        g_error_free (error);
+        g_free (object_path);
+        g_object_unref (daemon);
+        return NULL;
+    }
+    DBG("Started plugin daemon '%p' at path '%s' on conneciton '%p'",
+            daemon, object_path, daemon->priv->connection);
+    g_free (object_path);
+
+    /* Connect dbus remote plugin signals to handlers */
+    g_signal_connect_swapped (daemon->priv->dbus_remote_plugin,
+            "handle-cancel", G_CALLBACK (_handle_cancel_from_dbus), daemon);
+    g_signal_connect_swapped (daemon->priv->dbus_remote_plugin,
+            "handle-request", G_CALLBACK(_handle_request_from_dbus), daemon);
+    g_signal_connect_swapped (daemon->priv->dbus_remote_plugin,
+            "handle-request-initial",
+            G_CALLBACK(_handle_request_initial_from_dbus), daemon);
+    g_signal_connect_swapped (daemon->priv->dbus_remote_plugin,
+            "handle-user-action-finished",
+            G_CALLBACK(_handle_user_action_finished_from_dbus), daemon);
+    g_signal_connect_swapped (daemon->priv->dbus_remote_plugin,
+            "handle-refresh", G_CALLBACK(_handle_refresh_from_dbus), daemon);
+    g_signal_connect_swapped (daemon->priv->dbus_remote_plugin,
+            "handle-get-info", G_CALLBACK(_handle_get_info_from_dbus), daemon);
+
+    /* Connect plugin signals to handlers */
+    g_signal_connect_swapped (daemon->priv->plugin, "response",
+            G_CALLBACK (_handle_response_from_plugin), daemon);
+    g_signal_connect_swapped (daemon->priv->plugin, "response-final",
+            G_CALLBACK(_handle_response_final_from_plugin), daemon);
+    g_signal_connect_swapped (daemon->priv->plugin, "store",
+            G_CALLBACK(_handle_store_from_plugin), daemon);
+    g_signal_connect_swapped (daemon->priv->plugin, "error",
+            G_CALLBACK(_handle_error_from_plugin), daemon);
+    g_signal_connect_swapped (daemon->priv->plugin, "user-action-required",
+            G_CALLBACK(_handle_user_action_required_from_plugin), daemon);
+    g_signal_connect_swapped (daemon->priv->plugin, "refreshed",
+            G_CALLBACK(_handle_refreshed_from_plugin), daemon);
+    g_signal_connect_swapped (daemon->priv->plugin, "status-changed",
+            G_CALLBACK(_handle_status_changed_from_plugin), daemon);
+
+    g_signal_connect (daemon->priv->connection, "closed",
+            G_CALLBACK(_on_connection_closed), daemon);
+
+    return daemon;
+}
+
diff --git a/src/daemon/plugins/plugind/gsignond-plugin-daemon.h b/src/daemon/plugins/plugind/gsignond-plugin-daemon.h
new file mode 100644 (file)
index 0000000..55856ae
--- /dev/null
@@ -0,0 +1,70 @@
+/* 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) 2013 Intel Corporation.
+ *
+ * Contact: Imran Zaman <imran.zaman@intel.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_DAEMON_H_
+#define __GSIGNOND_PLUGIN_DAEMON_H_
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GSIGNOND_TYPE_PLUGIN_DAEMON  (gsignond_plugin_daemon_get_type())
+#define GSIGNOND_PLUGIN_DAEMON(obj)  (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+        GSIGNOND_TYPE_PLUGIN_DAEMON, GSignondPluginDaemon))
+#define GSIGNOND_PLUGIN_DAEMON_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST((klass), \
+        GSIGNOND_TYPE_PLUGIN_DAEMON, GSignondPluginDaemonClass))
+#define GSIGNOND_IS_PLUGIN_DAEMON(obj)  (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
+        GSIGNOND_TYPE_PLUGIN_DAEMON))
+#define GSIGNOND_IS_PLUGIN_DAEMON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\
+        GSIGNOND_TYPE_PLUGIN_DAEMON))
+#define GSIGNOND_PLUGIN_DAEMON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),\
+        GSIGNOND_TYPE_PLUGIN_DAEMON, GSignondPluginDaemonClass))
+
+typedef struct _GSignondPluginDaemon GSignondPluginDaemon;
+typedef struct _GSignondPluginDaemonClass GSignondPluginDaemonClass;
+typedef struct _GSignondPluginDaemonPrivate GSignondPluginDaemonPrivate;
+
+struct _GSignondPluginDaemon
+{
+    GObject parent;
+
+    /* priv */
+    GSignondPluginDaemonPrivate *priv;
+};
+
+struct _GSignondPluginDaemonClass
+{
+    GObjectClass parent_class;
+};
+
+GType gsignond_plugin_daemon_get_type();
+
+GSignondPluginDaemon *
+gsignond_plugin_daemon_new (
+        const gchar* filename,
+        const gchar* plugin_type);
+
+#endif /* __GSIGNOND_PLUGIN_DAEMON_H_ */
diff --git a/src/daemon/plugins/plugind/main.c b/src/daemon/plugins/plugind/main.c
new file mode 100644 (file)
index 0000000..07e1814
--- /dev/null
@@ -0,0 +1,171 @@
+/* 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) 2013 Intel Corporation.
+ *
+ * Contact: Imran Zaman <imran.zaman@intel.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 <config.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <glib-unix.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "gsignond/gsignond-log.h"
+#include "daemon/dbus/gsignond-dbus.h"
+#include "gsignond-plugin-daemon.h"
+
+static GSignondPluginDaemon *_daemon = NULL;
+static guint           _sig_source_id[2];
+
+static void
+_on_daemon_closed (gpointer data, GObject *server)
+{
+    _daemon = NULL;
+    DBG ("Daemon closed");
+    if (data) g_main_loop_quit ((GMainLoop *)data);
+}
+
+static gboolean
+_handle_quit_signal (gpointer user_data)
+{
+    GMainLoop *ml = (GMainLoop *) user_data;
+
+    g_return_val_if_fail (ml != NULL, FALSE);
+    DBG ("Received quit signal");
+    if (ml) g_main_loop_quit (ml);
+
+    return FALSE;
+}
+
+static void 
+_install_sighandlers (GMainLoop *main_loop)
+{
+    GSource *source = NULL;
+    GMainContext *ctx = g_main_loop_get_context (main_loop);
+
+    source = g_unix_signal_source_new (SIGTERM);
+    g_source_set_callback (source,
+                           _handle_quit_signal,
+                           main_loop,
+                           NULL);
+    _sig_source_id[0] = g_source_attach (source, ctx);
+    source = g_unix_signal_source_new (SIGINT);
+    g_source_set_callback (source,
+                           _handle_quit_signal,
+                           main_loop,
+                           NULL);
+    _sig_source_id[1] = g_source_attach (source, ctx);
+}
+
+static void
+_default_log_handler (
+        const gchar    *log_domain,
+        GLogLevelFlags  log_level,
+        const gchar    *message,
+        gpointer        unused_data)
+{
+    const gchar *strvect[16];
+    gchar *msg = NULL;
+    guint ind = 0;
+    if (log_domain) {
+        strvect[ind++] = log_domain;
+        strvect[ind++] = "-";
+    }
+    strvect[ind++] = "plugind";
+    if (log_level & G_LOG_LEVEL_ERROR)
+        strvect[ind++] = "-ERROR: ";
+    else if (log_level & G_LOG_LEVEL_CRITICAL)
+        strvect[ind++] = "-CRITICAL: ";
+    else if (log_level & G_LOG_LEVEL_WARNING)
+        strvect[ind++] = "-WARNING: ";
+    else if (log_level & G_LOG_LEVEL_MESSAGE)
+        strvect[ind++] = "-MESSAGE: ";
+    else if (log_level & G_LOG_LEVEL_INFO)
+        strvect[ind++] = "-INFO: ";
+    else if (log_level & G_LOG_LEVEL_DEBUG)
+        strvect[ind++] = "-DEBUG: ";
+    else
+        strvect[ind++] = ": ";
+    strvect[ind++] = message;
+    strvect[ind++] = NULL;
+
+    msg = g_strjoinv ("", (gchar**) strvect);
+    fprintf (stderr, "%s\n", msg);
+    fflush (stderr);
+    g_free (msg);
+}
+
+int main (int argc, char **argv)
+{
+    GError *error = NULL;
+    GMainLoop *main_loop = NULL;
+    GOptionContext *opt_context = NULL;
+    gchar **plugin_args = NULL;
+    GOptionEntry opt_entries[] = {
+        {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &plugin_args,
+                "Plugin Args", NULL},
+        {NULL}
+    };
+
+    g_type_init ();
+
+    g_log_set_default_handler (_default_log_handler, NULL);
+
+    opt_context = g_option_context_new ("SSO plugin daemon");
+    g_option_context_add_main_entries (opt_context, opt_entries, NULL);
+    g_option_context_parse (opt_context, &argc, &argv, &error);
+    g_option_context_free (opt_context);
+    if (error) {
+        DBG ("Error parsing options: %s", error->message);
+        g_error_free (error);
+        if (plugin_args) g_strfreev(plugin_args);
+        return -1;
+    }
+
+    _daemon = gsignond_plugin_daemon_new (plugin_args[0], plugin_args[1]);
+    g_strfreev(plugin_args);
+    if (_daemon == NULL) {
+        DBG ("Error creating daemon object");
+        return -1;
+    }
+
+    main_loop = g_main_loop_new (NULL, FALSE);
+    g_object_weak_ref (G_OBJECT (_daemon), _on_daemon_closed, main_loop);
+    _install_sighandlers(main_loop);
+
+    DBG ("Entering main event loop");
+
+    g_main_loop_run (main_loop);
+
+    if(_daemon) {
+        g_object_unref (_daemon);
+    }
+    if (main_loop) {
+        g_main_loop_unref (main_loop);
+    }
+
+    return 0;
+}
index 1ec44c0..b446a98 100644 (file)
@@ -164,12 +164,6 @@ gsignond_digest_plugin_cancel (GSignondPlugin *self)
 }
 
 static void
-gsignond_digest_plugin_abort (GSignondPlugin *self)
-{
-
-}
-
-static void
 gsignond_digest_plugin_request (
     GSignondPlugin *self,
     GSignondSessionData *session_data)
@@ -343,7 +337,6 @@ static void
 gsignond_plugin_interface_init (GSignondPluginInterface *iface)
 {
     iface->cancel = gsignond_digest_plugin_cancel;
-    iface->abort = gsignond_digest_plugin_abort;
     iface->request_initial = gsignond_digest_plugin_request_initial;
     iface->request = gsignond_digest_plugin_request;
     iface->user_action_finished = gsignond_digest_plugin_user_action_finished;
index cef2039..a4f64b5 100644 (file)
@@ -43,11 +43,6 @@ static void gsignond_password_plugin_cancel (GSignondPlugin *self)
     g_error_free(error);
 }
 
-static void gsignond_password_plugin_abort (GSignondPlugin *self)
-{
-    
-}
-
 static void gsignond_password_plugin_request (
     GSignondPlugin *self, GSignondSessionData *session_data)
 {
@@ -136,7 +131,6 @@ static void
 gsignond_plugin_interface_init (GSignondPluginInterface *iface)
 {
     iface->cancel = gsignond_password_plugin_cancel;
-    iface->abort = gsignond_password_plugin_abort;
     iface->request_initial = gsignond_password_plugin_request_initial;
     iface->request = gsignond_password_plugin_request;
     iface->user_action_finished = gsignond_password_plugin_user_action_finished;
index 485f0d9..9162f7f 100644 (file)
@@ -63,11 +63,6 @@ static void gsignond_ssotest_plugin_cancel (GSignondPlugin *plugin)
     self->priv->is_canceled = TRUE;
 }
 
-static void gsignond_ssotest_plugin_abort (GSignondPlugin *plugin)
-{
-    g_return_if_fail (GSIGNOND_IS_SSOTEST_PLUGIN (plugin));
-}
-
 static void gsignond_ssotest_plugin_request_initial (
     GSignondPlugin *plugin, GSignondSessionData *session_data, 
     const gchar *mechanism)
@@ -86,8 +81,7 @@ static void gsignond_ssotest_plugin_request_initial (
             gsignond_plugin_status_changed (GSIGNOND_PLUGIN (self),
                                             GSIGNOND_PLUGIN_STATE_WAITING,
                                             "hello from the test plugin");
-            INFO ("Signal is sent");
-            g_usleep (1000 * 1000 / 10);
+            g_usleep (1000 * 1000 / 100);
             g_main_context_iteration (NULL, FALSE);
         }
     }
@@ -205,7 +199,6 @@ static void
 gsignond_plugin_interface_init (GSignondPluginInterface *iface)
 {
     iface->cancel = gsignond_ssotest_plugin_cancel;
-    iface->abort = gsignond_ssotest_plugin_abort;
     iface->request_initial = gsignond_ssotest_plugin_request_initial;
     iface->user_action_finished = gsignond_ssotest_plugin_user_action_finished;
     iface->refresh = gsignond_ssotest_plugin_refresh;
index 0761d5e..7a20aac 100644 (file)
@@ -34,8 +34,9 @@ pluginproxytest_SOURCES = pluginproxytest.c
 pluginproxytest_CFLAGS = \
     $(GSIGNOND_CFLAGS) \
     $(CHECK_CFLAGS) \
+    -I$(top_srcdir)/src \
     -I$(top_srcdir)/src/daemon/plugins \
-    -I$(top_srcdir)/include/ 
+    -I$(top_srcdir)/include/
 
 pluginproxytest_LDADD = \
     $(top_builddir)/src/common/libgsignond-common.la \
@@ -44,4 +45,3 @@ pluginproxytest_LDADD = \
     $(CHECK_LIBS)
 
 
-
index 043adf0..614e030 100644 (file)
 #include <check.h>
 #include <stdlib.h>
 #include <glib-object.h>
+
 #include "gsignond-plugin-proxy.h"
 #include "gsignond-plugin-proxy-factory.h"
+#include "gsignond-plugin-remote.h"
 #include <gsignond/gsignond-plugin-loader.h>
 #include <gsignond/gsignond-error.h>
 #include <gsignond/gsignond-log.h>
 
+static GMainLoop *main_loop = NULL;
+
 typedef struct _GSignondAuthSession GSignondAuthSession;
 typedef struct _GSignondAuthSessionClass GSignondAuthSessionClass;
 
+static void
+_stop_mainloop ()
+{
+    if (main_loop) {
+        g_main_loop_quit (main_loop);
+    }
+}
+
+static void
+_start_mainloop ()
+{
+    g_main_loop_run (main_loop);
+}
+
+
+static void
+_setup ()
+{
+    g_type_init ();
+    if (main_loop == NULL) {
+        main_loop = g_main_loop_new (NULL, FALSE);
+    }
+}
+
+static void
+_teardown ()
+{
+    if (main_loop) {
+        _stop_mainloop ();
+        g_main_loop_unref (main_loop);
+        main_loop = NULL;
+    }
+}
+
 struct _GSignondAuthSession
 {
     GObject parent;
@@ -46,58 +84,23 @@ struct _GSignondAuthSessionClass
     GObjectClass parent_class;
 };
 
-G_DEFINE_TYPE (GSignondAuthSession, gsignond_auth_session,
-                        G_TYPE_OBJECT);
+G_DEFINE_TYPE (GSignondAuthSession, gsignond_auth_session, G_TYPE_OBJECT);
 
 static void
-gsignond_auth_session_init (GSignondAuthSession *self)
+gsignond_auth_session_init (
+        GSignondAuthSession *self)
 {
 
     
 }
 
 static void
-gsignond_auth_session_class_init (GSignondAuthSessionClass *klass)
+gsignond_auth_session_class_init (
+        GSignondAuthSessionClass *klass)
 {
 //    GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
 }
 
-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;
@@ -106,21 +109,23 @@ gboolean testing_proxy_process_queue_cancel = FALSE;
 gint proxy_process_queue_cancel_results = 0;
 
 void
-gsignond_auth_session_notify_process_result (GSignondAuthSession *iface,
-                                             GSignondSessionData *result,
-                                             gpointer user_data)
+gsignond_auth_session_notify_process_result (
+        GSignondAuthSession *iface,
+        GSignondSessionData *result,
+        gpointer user_data)
 {
     int i;
-    
+
+    DBG ("");
+
     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(user_data);
-        gsignond_plugin_proxy_cancel(proxy, iface);
+        _stop_mainloop ();
+
     } else if (testing_proxy_process_queue) {
         proxy_process_queue_results++;
         if (proxy_process_queue_results == 1) {
@@ -130,13 +135,17 @@ gsignond_auth_session_notify_process_result (GSignondAuthSession *iface,
             gsignond_session_data_set_username(data, "megauser");
             gsignond_session_data_set_secret(data, "megapassword");
 
-            gsignond_plugin_proxy_process(proxy, iface, data, "password", proxy);
-            gsignond_plugin_proxy_process(proxy, iface, data, "password", proxy);
+            gsignond_plugin_proxy_process(proxy, iface, data, "password",
+                    proxy);
+
+            gsignond_plugin_proxy_process(proxy, iface, data, "password",
+                    proxy);
     
             gsignond_dictionary_unref(data);
         }
         if (proxy_process_queue_results == 3) {
             testing_proxy_process_queue = FALSE;
+            _stop_mainloop ();
         }
     } else if (testing_proxy_process_queue_cancel) {
         proxy_process_queue_cancel_results++;
@@ -144,20 +153,16 @@ gsignond_auth_session_notify_process_result (GSignondAuthSession *iface,
             GSignondPluginProxy* proxy = GSIGNOND_PLUGIN_PROXY(user_data);
             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", proxy);
-    
+            for (i = 0; i < 9; i++) {
+                gsignond_plugin_proxy_process(proxy, iface, data, "mech1",
+                        proxy);
+            }
             gsignond_dictionary_unref(data);
         }
-        if (proxy_process_queue_cancel_results == 5) {
-            GSignondPluginProxy* proxy = GSIGNOND_PLUGIN_PROXY(user_data);
-            gsignond_plugin_proxy_cancel(proxy, iface);
-        }
         if (proxy_process_queue_cancel_results == 10) {
             testing_proxy_process_queue_cancel = FALSE;
+            _stop_mainloop ();
         }
     } else 
         fail_if(TRUE);    
@@ -165,55 +170,119 @@ gsignond_auth_session_notify_process_result (GSignondAuthSession *iface,
 
 void
 gsignond_auth_session_notify_process_error (
-                                                GSignondAuthSession *iface,
-                                                const GError *error,
-                                                gpointer user_data
-                  )
+        GSignondAuthSession *iface,
+        const GError *error,
+        gpointer user_data)
 {
+    DBG ("");
+
     if (testing_proxy_process_cancel) {
-        fail_if(error->code != GSIGNOND_ERROR_WRONG_STATE);
+        fail_if(error->code != GSIGNOND_ERROR_SESSION_CANCELED);
         testing_proxy_process_cancel = FALSE;
+        _stop_mainloop ();
     } else if (testing_proxy_process_queue_cancel) {
-        fail_if(error->code != GSIGNOND_ERROR_WRONG_STATE);
-    } else
-        fail_if(TRUE);
+        fail_if(error->code != GSIGNOND_ERROR_SESSION_CANCELED);
+        proxy_process_queue_cancel_results++;
+    }
+
 }
 
 void 
-gsignond_auth_session_notify_store (GSignondAuthSession *self, 
-                            GSignondSessionData *session_data)
+gsignond_auth_session_notify_store (
+        GSignondAuthSession *self,
+        GSignondSessionData *session_data)
 {
+    DBG ("");
     fail_if(TRUE);
 }
 
 void 
-gsignond_auth_session_notify_user_action_required (GSignondAuthSession *self, 
-                                           GSignondSignonuiData *session_data
-                                 )
+gsignond_auth_session_notify_user_action_required (
+        GSignondAuthSession *self,
+        GSignondSignonuiData *session_data)
 {
+    DBG ("");
     fail_if(TRUE);
 }
 
 void 
-gsignond_auth_session_notify_refreshed (GSignondAuthSession *self, 
-                                GSignondSignonuiData *session_data
-                                             )
+gsignond_auth_session_notify_refreshed (
+        GSignondAuthSession *self,
+        GSignondSignonuiData *session_data)
 {
+    DBG ("");
     fail_if(TRUE);
 }
 
 void 
-gsignond_auth_session_notify_state_changed (GSignondAuthSession *self, 
-                                     gint state, 
-                                     const gchar *message,
-                                     gpointer user_data
-                  )
+gsignond_auth_session_notify_state_changed (
+        GSignondAuthSession *self,
+        gint state,
+        const gchar *message,
+        gpointer user_data)
+{
+    if (testing_proxy_process_cancel &&
+            state == GSIGNOND_PLUGIN_STATE_WAITING) {
+        GSignondPluginProxy* proxy = GSIGNOND_PLUGIN_PROXY(user_data);
+        gsignond_plugin_proxy_cancel(proxy, self);
+    } else if (testing_proxy_process_queue_cancel &&
+            state == GSIGNOND_PLUGIN_STATE_WAITING &&
+            proxy_process_queue_cancel_results == 5) {
+        GSignondPluginProxy* proxy = GSIGNOND_PLUGIN_PROXY(user_data);
+        gsignond_plugin_proxy_cancel(proxy, self);
+    }
+}
+
+static void
+check_plugin_proxy(
+        GSignondPluginProxy* proxy,
+        gchar *type,
+        gchar **mechanisms)
 {
-    INFO("AuthSession state changed %d %s", state, message);
+    gchar* ptype = NULL;
+    gchar** pmechanisms = NULL;
+
+    fail_if(proxy == NULL);
+
+    g_object_get(proxy, "type", &ptype, "mechanisms", &pmechanisms, NULL);
+    fail_unless(g_strcmp0(ptype, type) == 0);
+    if (pmechanisms == NULL) {
+        fail_unless (mechanisms[0] == NULL);
+    } else {
+        fail_unless(g_strcmp0(pmechanisms[0], mechanisms[0]) == 0);
+        fail_unless(pmechanisms[1] == NULL && mechanisms[1] == NULL);
+    }
+
+    g_free(ptype);
+    g_strfreev(pmechanisms);
 }
 
+START_TEST (test_pluginproxy_create)
+{
+    DBG("test_pluginproxy_create\n");
+
+    gchar *pass_mechs[] = {"password", NULL};
+
+    GSignondConfig* config = gsignond_config_new();
+    fail_if(config == NULL);
+
+    GSignondPluginProxy* proxy2 = gsignond_plugin_proxy_new(config,
+            "absentplugin");
+    fail_if (proxy2 != NULL);
+
+    GSignondPluginProxy* proxy = gsignond_plugin_proxy_new(config, "password");
+    fail_if (proxy == NULL);
+    check_plugin_proxy(proxy, "password", pass_mechs);
+
+    g_object_unref(proxy);
+    g_object_unref(config);
+}
+END_TEST
+
 START_TEST (test_pluginproxy_process)
 {
+    DBG("test_pluginproxy_process\n");
+
     GSignondConfig* config = gsignond_config_new();
     fail_if(config == NULL);
     
@@ -225,11 +294,16 @@ START_TEST (test_pluginproxy_process)
     gsignond_session_data_set_username(data, "megauser");
     gsignond_session_data_set_secret(data, "megapassword");
     
-    GSignondAuthSession* test_auth_session = g_object_new(gsignond_auth_session_get_type(), NULL);
+    GSignondAuthSession* test_auth_session =
+            g_object_new(gsignond_auth_session_get_type(), NULL);
 
     testing_proxy_process = TRUE;
 
-    gsignond_plugin_proxy_process(proxy, test_auth_session, data, "password", proxy);
+    gsignond_plugin_proxy_process(proxy, test_auth_session, data, "password",
+            proxy);
+
+    _start_mainloop ();
+
     fail_if(testing_proxy_process);
     
     gsignond_dictionary_unref(data);
@@ -241,22 +315,27 @@ END_TEST
 
 START_TEST (test_pluginproxy_process_cancel)
 {
+    DBG("test_pluginproxy_process_cancel\n");
+
     GSignondConfig* config = gsignond_config_new();
     fail_if(config == NULL);
     
-    GSignondPluginProxy* proxy = gsignond_plugin_proxy_new(config, "password");
+    GSignondPluginProxy* proxy = gsignond_plugin_proxy_new(config, "ssotest");
     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");
 
-    GSignondAuthSession* test_auth_session = g_object_new(gsignond_auth_session_get_type(), NULL);
+    GSignondAuthSession* test_auth_session = g_object_new(
+            gsignond_auth_session_get_type(), NULL);
     
     testing_proxy_process_cancel = TRUE;
     
-    gsignond_plugin_proxy_process(proxy, test_auth_session, data, "password", proxy);
+    gsignond_plugin_proxy_process(proxy, test_auth_session, data, "mech1",
+            proxy);
+
+    _start_mainloop ();
+
     fail_if(testing_proxy_process_cancel);
     
     gsignond_dictionary_unref(data);
@@ -268,6 +347,8 @@ END_TEST
 
 START_TEST (test_pluginproxy_process_queue)
 {
+    DBG("test_pluginproxy_process_queue\n");
+
     GSignondConfig* config = gsignond_config_new();
     fail_if(config == NULL);
     
@@ -279,11 +360,15 @@ START_TEST (test_pluginproxy_process_queue)
     gsignond_session_data_set_username(data, "megauser");
     gsignond_session_data_set_secret(data, "megapassword");
 
-    GSignondAuthSession* test_auth_session = g_object_new(gsignond_auth_session_get_type(), NULL);
+    GSignondAuthSession* test_auth_session = g_object_new(
+            gsignond_auth_session_get_type(), NULL);
     
     testing_proxy_process_queue = TRUE;
     
-    gsignond_plugin_proxy_process(proxy, test_auth_session, data, "password", proxy);
+    gsignond_plugin_proxy_process(proxy, test_auth_session, data, "password",
+            proxy);
+    _start_mainloop ();
+
     fail_if(testing_proxy_process_queue);
     fail_if(proxy_process_queue_results < 3);
 
@@ -299,19 +384,22 @@ START_TEST (test_pluginproxy_process_queue_cancel)
     GSignondConfig* config = gsignond_config_new();
     fail_if(config == NULL);
     
-    GSignondPluginProxy* proxy = gsignond_plugin_proxy_new(config, "password");
+    GSignondPluginProxy* proxy = gsignond_plugin_proxy_new(config, "ssotest");
     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");
 
-    GSignondAuthSession* test_auth_session = g_object_new(gsignond_auth_session_get_type(), NULL);
+    GSignondAuthSession* test_auth_session = g_object_new(
+            gsignond_auth_session_get_type(), NULL);
     
     testing_proxy_process_queue_cancel = TRUE;
     
-    gsignond_plugin_proxy_process(proxy, test_auth_session, data, "password", proxy);
+    gsignond_plugin_proxy_process(proxy, test_auth_session, data, "mech1",
+            proxy);
+
+    _start_mainloop ();
+
     fail_if(testing_proxy_process_queue_cancel);
     fail_if(proxy_process_queue_cancel_results != 10);
 
@@ -324,23 +412,34 @@ END_TEST
 
 START_TEST (test_pluginproxyfactory_methods_and_mechanisms)
 {
+    DBG("");
     GSignondConfig* config = gsignond_config_new();
     fail_if(config == NULL);
     
-    GSignondPluginProxyFactory* factory = gsignond_plugin_proxy_factory_new(config);
+    GSignondPluginProxyFactory* factory = gsignond_plugin_proxy_factory_new(
+            config);
     fail_if(factory == NULL);
+    const gchar *pass_method = NULL;
+    const gchar** pmethods = NULL;
     
-    const gchar** methods = gsignond_plugin_proxy_factory_get_plugin_types(factory);
+    const gchar** methods = gsignond_plugin_proxy_factory_get_plugin_types(
+            factory);
     fail_if(methods == NULL);
-    fail_if(strcmp(methods[0], "password") != 0);
-    fail_if(methods[1] != NULL);
-    
-    const gchar** mechanisms = gsignond_plugin_proxy_factory_get_plugin_mechanisms(factory, methods[0]);
+    pmethods = methods;
+    while (pmethods[0] != NULL) {
+        DBG ("Method %s", pmethods[0]);
+        if (g_strcmp0 (pmethods[0], "password") == 0) {
+            pass_method = pmethods[0];
+        }
+        pmethods++;
+    }
+    const gchar** mechanisms =
+            gsignond_plugin_proxy_factory_get_plugin_mechanisms(factory,
+                    pass_method);
     fail_if(mechanisms == NULL);
     fail_if(strcmp(mechanisms[0], "password") != 0);
     fail_if(mechanisms[1] != NULL);
     
-
     g_object_unref(factory);
     g_object_unref(config);
 }
@@ -348,13 +447,17 @@ END_TEST
 
 START_TEST (test_pluginproxyfactory_get)
 {
+    DBG("");
+    gchar *pass_mechs[] = {"password", NULL};
     GSignondConfig* config = gsignond_config_new();
     fail_if(config == NULL);
     
-    GSignondPluginProxyFactory* factory = gsignond_plugin_proxy_factory_new(config);
+    GSignondPluginProxyFactory* factory = gsignond_plugin_proxy_factory_new(
+            config);
     fail_if(factory == NULL);
     
-    fail_if(gsignond_plugin_proxy_factory_get_plugin(factory, "absentplugin") != NULL);
+    fail_if(gsignond_plugin_proxy_factory_get_plugin(factory, "absentplugin")
+            != NULL);
 
     GSignondPluginProxy* proxy1 = gsignond_plugin_proxy_factory_get_plugin(
         factory, "password");
@@ -364,7 +467,7 @@ START_TEST (test_pluginproxyfactory_get)
         factory, "password");
     fail_if(proxy1 == NULL || proxy2 == NULL || proxy3 == NULL);
     fail_if(proxy1 != proxy3 || proxy1 != proxy2);
-    check_plugin_proxy(proxy1);
+    check_plugin_proxy(proxy1, "password", pass_mechs);
 
     g_object_unref(proxy1);
     g_object_unref(proxy2);
@@ -377,17 +480,20 @@ END_TEST
 
 START_TEST (test_pluginproxyfactory_add)
 {
+    DBG("");
     GSignondConfig* config = gsignond_config_new();
     fail_if(config == NULL);
     
-    GSignondPluginProxyFactory* factory = gsignond_plugin_proxy_factory_new(config);
+    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, proxy) == FALSE);
     fail_if(gsignond_plugin_proxy_factory_add_plugin(factory, proxy) == TRUE);
-    fail_if(gsignond_plugin_proxy_factory_get_plugin(factory, "password") != proxy);
+    fail_if(gsignond_plugin_proxy_factory_get_plugin(factory, "password")
+            != proxy);
 
     g_object_unref(proxy);
     g_object_unref(factory);
@@ -395,23 +501,23 @@ START_TEST (test_pluginproxyfactory_add)
 }
 END_TEST
 
-
 Suite* pluginproxy_suite (void)
 {
     Suite *s = suite_create ("Plugin proxy");
     
     /* Core test case */
     TCase *tc_core = tcase_create ("Tests");
+    tcase_add_checked_fixture (tc_core, _setup, _teardown);
+
     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_methods_and_mechanisms);
     tcase_add_test (tc_core, test_pluginproxyfactory_get);
     tcase_add_test (tc_core, test_pluginproxyfactory_add);
+
     suite_add_tcase (s, tc_core);
     return s;
 }
@@ -420,8 +526,6 @@ int main (void)
 {
     int number_failed;
     
-    g_type_init();
-    
     Suite *s = pluginproxy_suite();
     SRunner *sr = srunner_create(s);
     srunner_run_all(sr, CK_NORMAL);