[network-manager-applet/th/vpn-service-info-bgo767197: 2/8] c-e: allow one VPN plugin to create multiple "Add" entires per provided service-type



commit ebfa960cb41fefdf1e56815c797d6c62ee623ade
Author: Thomas Haller <thaller redhat com>
Date:   Fri Jun 3 17:31:48 2016 +0200

    c-e: allow one VPN plugin to create multiple "Add" entires per provided service-type
    
    One VPN plugin can support multiple "service-types", also known as
    "aliases". These service-types look like a D-Bus bus name and are stored
    in the connection as vpn.service-type.
    
    Previously already, one VPN plugin could edit connections with different
    service-types, using aliases. That is for example used for nm-libreswan,
    which supports editing both libreswan and openswan types.
    
    However, in "Connection Add" one plugin could only create one entry
    in the list of supported types. Thus, the "vpn.service-type" could
    only be set to the main service-type, and one plugin could not create
    connection for their aliases.
    
    Extend that, by allowing the VPN to specify that it supports addition
    for the aliased service-types.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=767197

 shared/Makefile.am                         |    3 +-
 shared/nm-vpn-editor-plugin-call.h         |  407 ++++++++++++++++++++++++++++
 src/connection-editor/ce-new-connection.ui |   10 +-
 src/connection-editor/connection-helpers.c |  100 +++++---
 src/connection-editor/vpn-helpers.c        |    1 +
 5 files changed, 481 insertions(+), 40 deletions(-)
---
diff --git a/shared/Makefile.am b/shared/Makefile.am
index 8ee639d..28b0bf2 100644
--- a/shared/Makefile.am
+++ b/shared/Makefile.am
@@ -4,4 +4,5 @@ EXTRA_DIST = \
      nm-default.h \
      nm-glib.h \
      nm-macros-internal.h \
-     nm-test-utils.h
+     nm-test-utils.h \
+     nm-vpn-editor-plugin-call.h
diff --git a/shared/nm-vpn-editor-plugin-call.h b/shared/nm-vpn-editor-plugin-call.h
new file mode 100644
index 0000000..cad8143
--- /dev/null
+++ b/shared/nm-vpn-editor-plugin-call.h
@@ -0,0 +1,407 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ */
+
+#ifndef __NM_VPN_EDITOR_PLUGIN_CALL_H__
+#define __NM_VPN_EDITOR_PLUGIN_CALL_H__
+
+/* This header is an internal, header-only file that can be copied to
+ * other projects to call well-known service functions on VPN plugins. */
+
+#include <NetworkManager.h>
+
+/* we make use of otherinternal header files, you need those too. */
+#include "gsystem-local-alloc.h"
+#include "nm-macros-internal.h"
+
+/*****************************************************************************/
+
+/**
+ * NMVpnEditorPluginServiceFlags:
+ * @NM_VPN_EDITOR_PLUGIN_SERVICE_FLAGS_NONE: no flags
+ * @NM_VPN_EDITOR_PLUGIN_SERVICE_FLAGS_CAN_ADD: whether the plugin can
+ *   add a new connection for the given service-type.
+ **/
+typedef enum { /*< skip >*/
+       NM_VPN_EDITOR_PLUGIN_SERVICE_FLAGS_NONE     = 0x00,
+       NM_VPN_EDITOR_PLUGIN_SERVICE_FLAGS_CAN_ADD  = 0x01,
+} NMVpnEditorPluginServiceFlags;
+
+/*****************************************************************************/
+
+/**
+ * NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_INFO: name of call "get-service-info".
+ *   This call has 1 input argument:
+ *     service-type (string): analog to NM_VPN_EDITOR_PLUGIN_SERVICE
+ *     it specifies for which service-type the information is requested.
+ *     This can either be the main service-type or an alias.
+ *   This call has 3 output arguments:
+ *     short-name (string): for the main service-type, this shall return [VPN Connection].name.
+ *        Otherwise, it is a short-name to refer to service-type.
+ *     pretty-name (string): for the main service-type, this shall return NM_VPN_EDITOR_PLUGIN_NAME.
+ *        It's a localized, pretty name of the service-type.
+ *     description (string): for the main service-type, this shall return NM_VPN_EDITOR_PLUGIN_DESCRIPTION
+ *        It's a localized, description for the service-type.
+ *     service flags (uint): flags for the service-type.
+ */
+#define NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_INFO "get-service-info"
+
+/**
+ * NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAILS: name of call "get-service-add-details".
+ *   For one particular service-type, the UI might want to show multiple "Add new connection"
+ *   entires. That is controlled by passing around "add-details".
+ *   The "get-service-add-details" returns optionally a list of "add-details" if it wishes
+ *   to generate multiple add entries.
+ *   This call has 1 input argument:
+ *     service-type: string: analog to NM_VPN_EDITOR_PLUGIN_SERVICE or an service-type
+ *        alias.
+ *   This call has 1 output argument:
+ *     add-details: strv: a list of details that can be passed to "get-service-add-detail"
+ *        call.
+ */
+#define NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAILS "get-service-add-details"
+
+/**
+ * NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAIL: if the plugin supports "add-details"
+ *   as indicated by "get-service-add-details", return more information.
+ *   This call has 2 input arguments:
+ *     service-name: string: analog to NM_VPN_EDITOR_PLUGIN_SERVICE or an service-type
+ *        alias. This was passed to "get-service-add-details" call.
+ *     add-detail: a detail for which the information is requested.
+ *   This call has 1 output argument:
+ *     pretty-name: (string), a localized name for what is to be added. Similar to
+ *       NM_VPN_EDITOR_PLUGIN_NAME.
+ *     description: (string), a localized descirption, similar to NM_VPN_EDITOR_PLUGIN_DESCRIPTION.
+ *     add-detail-key: (string), when creating such a connection of type "service-type","add-detail",
+ *       the user shall create a NMConnection with setting "service-type". It also sets the VPN
+ *       key "add-detail-key" to the value "add-detail", so that the plugin knows which connection
+ *       is to be created.
+ *     flags: (uint), additional flags, currently unused.
+ */
+#define NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAIL "get-service-add-detail"
+
+/*****************************************************************************
+ * Call
+ *
+ * The following wrap the calling of generic functions for a VPN plugin.
+ * They are used by callers (for example nm-connection-editor).
+ *****************************************************************************/
+
+static inline gboolean
+nm_vpn_editor_plugin_get_service_info (NMVpnEditorPlugin *plugin,
+                                       const char *service_type,
+                                       char **out_short_name,
+                                       char **out_pretty_name,
+                                       char **out_description,
+                                       NMVpnEditorPluginServiceFlags *out_flags)
+{
+       gs_free char *short_name_local = NULL;
+       gs_free char *pretty_name_local = NULL;
+       gs_free char *description_local = NULL;
+       guint flags_local = 0;
+
+       g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), FALSE);
+       g_return_val_if_fail (service_type, FALSE);
+
+       if (!nm_vpn_editor_plugin_call (plugin,
+                                       NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_INFO,
+                                       NULL,
+                                       G_TYPE_STRING, &service_type,
+                                       G_TYPE_INVALID,
+                                       G_TYPE_STRING, &short_name_local,
+                                       G_TYPE_STRING, &pretty_name_local,
+                                       G_TYPE_STRING, &description_local,
+                                       G_TYPE_UINT,   &flags_local,
+                                       G_TYPE_INVALID))
+               return FALSE;
+       NM_SET_OUT (out_short_name, g_steal_pointer (&short_name_local));
+       NM_SET_OUT (out_pretty_name, g_steal_pointer (&pretty_name_local));
+       NM_SET_OUT (out_description, g_steal_pointer (&description_local));
+       NM_SET_OUT (out_flags, flags_local);
+       return TRUE;
+}
+
+static inline char **
+nm_vpn_editor_plugin_get_service_add_details (NMVpnEditorPlugin *plugin,
+                                              const char *service_name)
+{
+       char **details = NULL;
+
+       g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), FALSE);
+       g_return_val_if_fail (service_name, FALSE);
+
+       if (!nm_vpn_editor_plugin_call (plugin,
+                                       NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAILS,
+                                       NULL,
+                                       G_TYPE_STRING, service_name,
+                                       G_TYPE_INVALID,
+                                       G_TYPE_STRV,   &details,
+                                       G_TYPE_INVALID))
+               g_clear_pointer (&details, g_strfreev);
+       else if (!details)
+               return g_new0 (char *, 1);
+       return details;
+}
+
+static inline gboolean
+nm_vpn_editor_plugin_get_service_add_detail (NMVpnEditorPlugin *plugin,
+                                             const char *service_type,
+                                             const char *add_detail,
+                                             char **out_pretty_name,
+                                             char **out_description,
+                                             char **out_add_detail_key,
+                                             guint *out_flags)
+{
+       gs_free char *pretty_name_local = NULL;
+       gs_free char *description_local = NULL;
+       gs_free char *add_detail_key_local = NULL;
+       guint flags_local = 0;
+
+       g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), FALSE);
+       g_return_val_if_fail (service_type, FALSE);
+       g_return_val_if_fail (add_detail, FALSE);
+
+       if (!nm_vpn_editor_plugin_call (plugin,
+                                       NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAIL,
+                                       NULL,
+                                       G_TYPE_STRING, service_type,
+                                       G_TYPE_STRING, add_detail,
+                                       G_TYPE_INVALID,
+                                       G_TYPE_STRING, &pretty_name_local,
+                                       G_TYPE_STRING, &description_local,
+                                       G_TYPE_STRING, &add_detail_key_local,
+                                       G_TYPE_UINT,   out_flags ?: &flags_local,
+                                       G_TYPE_INVALID))
+               return FALSE;
+       NM_SET_OUT (out_pretty_name, g_steal_pointer (&pretty_name_local));
+       NM_SET_OUT (out_description, g_steal_pointer (&description_local));
+       NM_SET_OUT (out_add_detail_key, g_steal_pointer (&add_detail_key_local));
+       return TRUE;
+}
+
+/*****************************************************************************
+ * Implementation
+ *
+ * The following glue code can be used to implement calls in a VPN plugin.
+ * Register your hocks via NM_VPN_EDITOR_PLUGIN_CALL_SET_*() and
+ * NM_VPN_EDITOR_PLUGIN_CALL_SETUP().
+ *****************************************************************************/
+
+static gboolean (*const _nm_vpn_editor_plugin_call_impl_get_service_info) (NMVpnEditorPlugin *plugin,
+                                                                           const char *service_type,
+                                                                           char **out_short_name,
+                                                                           char **out_pretty_name,
+                                                                           char **out_description,
+                                                                           NMVpnEditorPluginServiceFlags 
*out_flags,
+                                                                           GError **error);
+
+#define NM_VPN_EDITOR_PLUGIN_CALL_SET_GET_SERVICE_INFO(fcn) \
+static gboolean (*const _nm_vpn_editor_plugin_call_impl_get_service_info) (NMVpnEditorPlugin *plugin, \
+                                                                           const char *service_type, \
+                                                                           char **out_short_name, \
+                                                                           char **out_pretty_name, \
+                                                                           char **out_description, \
+                                                                           NMVpnEditorPluginServiceFlags 
*out_flags, \
+                                                                           GError **error) = (fcn)
+
+static gboolean (*const _nm_vpn_editor_plugin_call_impl_get_service_add_details) (NMVpnEditorPlugin *plugin,
+                                                                                  const char *service_type,
+                                                                                  char ***out_add_details,
+                                                                                  GError **error);
+
+#define NM_VPN_EDITOR_PLUGIN_CALL_SET_GET_SERVICE_ADD_DETAILS(fcn) \
+static gboolean (*const _nm_vpn_editor_plugin_call_impl_get_service_add_details) (NMVpnEditorPlugin *plugin, 
\
+                                                                                  const char *service_type, \
+                                                                                  char ***out_add_details, \
+                                                                                  GError **error) = (fcn)
+
+static gboolean (*const _nm_vpn_editor_plugin_call_impl_get_service_add_detail) (NMVpnEditorPlugin *plugin,
+                                                                                 const char *service_type,
+                                                                                 const char *add_detail,
+                                                                                 char **out_pretty_name,
+                                                                                 char **out_description,
+                                                                                 char **out_add_detail_key,
+                                                                                 guint *out_flags,
+                                                                                 GError **error);
+
+#define NM_VPN_EDITOR_PLUGIN_CALL_SET_GET_SERVICE_ADD_DETAIL(fcn) \
+static gboolean (*const _nm_vpn_editor_plugin_call_impl_get_service_add_detail) (NMVpnEditorPlugin *plugin, \
+                                                                                 const char *service_type, \
+                                                                                 const char *add_detail, \
+                                                                                 char **out_pretty_name, \
+                                                                                 char **out_description, \
+                                                                                 char **out_add_detail_key, \
+                                                                                 guint *out_flags, \
+                                                                                 GError **error) = (fcn)
+
+static inline gboolean
+_nm_vpn_editor_plugin_call_get_signature (NMVpnEditorPlugin *plugin,
+                                          const char *request,
+                                          gboolean *free_types,
+                                          GType **types_in,
+                                          GType **types_out)
+{
+       if (   _nm_vpn_editor_plugin_call_impl_get_service_info
+           && nm_streq (request, NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_INFO)) {
+               static GType t_in[] = { G_TYPE_STRING, 0 };
+               static GType t_out[] = { G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, 0 };
+
+               *types_in = t_in;
+               *types_out = t_out;
+               return TRUE;
+       }
+       if (   _nm_vpn_editor_plugin_call_impl_get_service_add_details
+           && nm_streq (request, NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAILS)) {
+               static GType t_in[] = { G_TYPE_STRING, 0 };
+               static GType t_out[] = { 0, 0 };
+
+               if (G_UNLIKELY (t_out[0] == 0))
+                       t_out[0] = G_TYPE_STRV;
+
+               *types_in = t_in;
+               *types_out = t_out;
+               return TRUE;
+       }
+       if (   _nm_vpn_editor_plugin_call_impl_get_service_add_detail
+           && nm_streq (request, NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAIL)) {
+               static GType t_in[] = { G_TYPE_STRING, G_TYPE_STRING, 0 };
+               static GType t_out[] = { G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, 0 };
+
+               *types_in = t_in;
+               *types_out = t_out;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+static inline gboolean
+_nm_vpn_editor_plugin_call_fail_unknown_service_type (GError **error, const char *service_type)
+{
+       if (error && !*error) {
+               g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_CALL_INVALID_ARGUMENT,
+                            _("Unknown service-type %s%s%s"), NM_PRINT_FMT_QUOTE_STRING (service_type));
+       }
+       return FALSE;
+}
+
+static inline gboolean
+_nm_vpn_editor_plugin_call (NMVpnEditorPlugin *plugin,
+                            const char *request,
+                            GError **error,
+                            const GValue *const*args_in,
+                            GValue *const*args_out)
+{
+       if (   _nm_vpn_editor_plugin_call_impl_get_service_info
+           && nm_streq (request, NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_INFO)) {
+               const char *service_type;
+               gs_free char *short_name = NULL;
+               gs_free char *pretty_name = NULL;
+               gs_free char *description = NULL;
+               NMVpnEditorPluginServiceFlags flags = 0;
+
+               service_type = g_value_get_string (args_in[0]);
+
+               if (!service_type)
+                       return _nm_vpn_editor_plugin_call_fail_unknown_service_type (error, service_type);
+
+               if (_nm_vpn_editor_plugin_call_impl_get_service_info (plugin,
+                                                                     service_type,
+                                                                     &short_name,
+                                                                     &pretty_name,
+                                                                     &description,
+                                                                     &flags,
+                                                                        error)) {
+                       g_value_take_string (args_out[0], g_steal_pointer (&short_name));
+                       g_value_take_string (args_out[1], g_steal_pointer (&pretty_name));
+                       g_value_take_string (args_out[2], g_steal_pointer (&description));
+                       g_value_set_uint (args_out[3], flags);
+                       return TRUE;
+               }
+               return _nm_vpn_editor_plugin_call_fail_unknown_service_type (error, service_type);
+       }
+
+       if (   _nm_vpn_editor_plugin_call_impl_get_service_add_details
+           && nm_streq (request, NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAILS)) {
+               const char *service_type;
+
+               service_type = g_value_get_string (args_in[0]);
+               if (service_type) {
+                       gs_strfreev char **add_details = NULL;
+
+                       if (_nm_vpn_editor_plugin_call_impl_get_service_add_details (plugin,
+                                                                                    service_type,
+                                                                                    &add_details,
+                                                                                    error)) {
+                               g_value_take_boxed (args_out[0], g_steal_pointer (&add_details));
+                               return TRUE;
+                       }
+               }
+               return _nm_vpn_editor_plugin_call_fail_unknown_service_type (error, service_type);
+       }
+
+       if (   _nm_vpn_editor_plugin_call_impl_get_service_add_detail
+           && nm_streq (request, NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAIL)) {
+               const char *service_type;
+               const char *add_detail;
+               gs_free char *pretty_name = NULL;
+               gs_free char *description = NULL;
+               gs_free char *add_detail_key = NULL;
+               guint flags = 0;
+
+               service_type = g_value_get_string (args_in[0]);
+               add_detail = g_value_get_string (args_in[1]);
+
+               if (!service_type)
+                       return _nm_vpn_editor_plugin_call_fail_unknown_service_type (error, service_type);
+
+               if (!add_detail) {
+                       g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_CALL_INVALID_ARGUMENT,
+                                    _("missing add_detail argument"));
+                       return FALSE;
+               }
+               if (_nm_vpn_editor_plugin_call_impl_get_service_add_detail (plugin,
+                                                                           service_type,
+                                                                           add_detail,
+                                                                           &pretty_name,
+                                                                           &description,
+                                                                           &add_detail_key,
+                                                                           &flags,
+                                                                           error)) {
+                       g_value_take_string (args_out[0], g_steal_pointer (&pretty_name));
+                       g_value_take_string (args_out[1], g_steal_pointer (&description));
+                       g_value_take_string (args_out[2], g_steal_pointer (&add_detail_key));
+                       g_value_set_uint (args_out[3], flags);
+                       return TRUE;
+               }
+               return _nm_vpn_editor_plugin_call_fail_unknown_service_type (error, service_type);
+       }
+
+       g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_CALL_INVALID_ARGUMENT,
+                    _("Unknown request %s"), request);
+       return FALSE;
+}
+
+static inline void
+NM_VPN_EDITOR_PLUGIN_CALL_SETUP (NMVpnEditorPluginInterface *iface_class)
+{
+       iface_class->call_get_signature = _nm_vpn_editor_plugin_call_get_signature;
+       iface_class->call = _nm_vpn_editor_plugin_call;
+}
+
+#endif /* __NM_VPN_EDITOR_PLUGIN_CALL_H__ */
diff --git a/src/connection-editor/ce-new-connection.ui b/src/connection-editor/ce-new-connection.ui
index ec4a3c9..3512dbb 100644
--- a/src/connection-editor/ce-new-connection.ui
+++ b/src/connection-editor/ce-new-connection.ui
@@ -4,14 +4,16 @@
   <requires lib="gtk+" version="3.0"/>
   <object class="GtkListStore" id="new_connection_combo_model">
     <columns>
-      <!-- column-name name -->
+      <!-- column-name name, COL_MARKUP -->
       <column type="gchararray"/>
-      <!-- column-name sensitive -->
+      <!-- column-name sensitive, COL_SENSITIVE -->
       <column type="gboolean"/>
-      <!-- column-name new_func -->
+      <!-- column-name new_func, COL_NEW_FUNC -->
       <column type="gpointer"/>
-      <!-- column-name vpn_plugin -->
+      <!-- column-name vpn_plugin, COL_VPN_PLUGIN -->
       <column type="GObject"/>
+      <!-- column-name vpn_service_type, COL_VPN_SERVICE_TYPE -->
+      <column type="gchararray"/>
     </columns>
   </object>
   <object class="GtkDialog" id="new_connection_type_dialog">
diff --git a/src/connection-editor/connection-helpers.c b/src/connection-editor/connection-helpers.c
index 9cc789c..997006c 100644
--- a/src/connection-editor/connection-helpers.c
+++ b/src/connection-editor/connection-helpers.c
@@ -35,11 +35,13 @@
 #include "page-vlan.h"
 #include "page-vpn.h"
 #include "vpn-helpers.h"
+#include "nm-vpn-editor-plugin-call.h"
 
 #define COL_MARKUP     0
 #define COL_SENSITIVE  1
 #define COL_NEW_FUNC   2
 #define COL_VPN_PLUGIN 3
+#define COL_VPN_SERVICE_TYPE 4
 
 static gint
 sort_types (gconstpointer a, gconstpointer b)
@@ -141,8 +143,10 @@ combo_changed_cb (GtkComboBox *combo, gpointer user_data)
        GtkLabel *label = GTK_LABEL (user_data);
        GtkTreeModel *model;
        GtkTreeIter iter;
-       NMVpnEditorPlugin *plugin = NULL;
-       char *description, *markup;
+       gs_unref_object NMVpnEditorPlugin *plugin = NULL;
+       gs_free char *service_type = NULL;
+       gs_free char *description = NULL;
+       gs_free char *markup = NULL;
 
        if (!gtk_combo_box_get_active_iter (combo, &iter))
                goto error;
@@ -151,19 +155,21 @@ combo_changed_cb (GtkComboBox *combo, gpointer user_data)
        if (!model)
                goto error;
 
-       gtk_tree_model_get (model, &iter, COL_VPN_PLUGIN, &plugin, -1);
-       if (!plugin)
+       gtk_tree_model_get (model, &iter,
+                           COL_VPN_PLUGIN, &plugin,
+                           COL_VPN_SERVICE_TYPE, &service_type,
+                           -1);
+       if (!plugin || !service_type)
                goto error;
 
-       g_object_get (G_OBJECT (plugin), NM_VPN_EDITOR_PLUGIN_DESCRIPTION, &description, NULL);
-       g_object_unref (plugin);
+       if (!nm_vpn_editor_plugin_get_service_info (plugin, service_type, NULL, NULL, &description, NULL))
+               g_object_get (G_OBJECT (plugin), NM_VPN_EDITOR_PLUGIN_DESCRIPTION, &description, NULL);
+
        if (!description)
                goto error;
 
        markup = g_markup_printf_escaped ("<i>%s</i>", description);
        gtk_label_set_markup (label, markup);
-       g_free (markup);
-       g_free (description);
        return;
 
 error:
@@ -259,24 +265,56 @@ set_up_connection_type_combo (GtkComboBox *combo,
        }
 
        for (p = vpn_plugins; p; p = p->next) {
-               NMVpnEditorPlugin *plugin = nm_vpn_plugin_info_get_editor_plugin (p->data);
-               char *desc;
+               NMVpnPluginInfo *plugin_info = p->data;
+               NMVpnEditorPlugin *plugin;
+               const char *const*aliases;
+               const char *service_type;
+               gboolean is_alias = FALSE;
+
+               plugin = nm_vpn_plugin_info_get_editor_plugin (plugin_info);
+               if (!plugin)
+                       continue;
 
-               g_object_get (plugin, NM_VPN_EDITOR_PLUGIN_NAME, &desc, NULL);
+               service_type = nm_vpn_plugin_info_get_service (plugin_info);
+               aliases = nm_vpn_plugin_info_get_aliases (plugin_info);
+
+               for (;;) {
+                       gs_free char *pretty_name = NULL;
+                       NMVpnEditorPluginServiceFlags flags;
+
+                       if (!nm_vpn_editor_plugin_get_service_info (plugin, service_type, NULL, &pretty_name, 
NULL, &flags)) {
+                               if (!is_alias)
+                                       goto next;
+                               g_object_get (plugin, NM_VPN_EDITOR_PLUGIN_NAME, &pretty_name, NULL);
+                               flags = NM_VPN_EDITOR_PLUGIN_SERVICE_FLAGS_CAN_ADD;
+                       }
+                       if (!pretty_name)
+                               goto next;
+                       if (!NM_FLAGS_HAS (flags, NM_VPN_EDITOR_PLUGIN_SERVICE_FLAGS_CAN_ADD))
+                               goto next;
+
+                       if (show_headers)
+                               markup = g_markup_printf_escaped ("    %s", pretty_name);
+                       else
+                               markup = g_markup_escape_text (pretty_name, -1);
 
-               if (show_headers)
-                       markup = g_markup_printf_escaped ("    %s", desc);
-               else
-                       markup = g_markup_escape_text (desc, -1);
-               gtk_list_store_append (model, &iter);
-               gtk_list_store_set (model, &iter,
-                                   COL_MARKUP, markup,
-                                   COL_SENSITIVE, TRUE,
-                                   COL_NEW_FUNC, list[vpn_index].new_connection_func,
-                                   COL_VPN_PLUGIN, plugin,
-                                   -1);
-               g_free (markup);
-               g_free (desc);
+                       gtk_list_store_append (model, &iter);
+                       gtk_list_store_set (model, &iter,
+                                           COL_MARKUP, markup,
+                                           COL_SENSITIVE, TRUE,
+                                           COL_NEW_FUNC, list[vpn_index].new_connection_func,
+                                           COL_VPN_PLUGIN, plugin,
+                                           COL_VPN_SERVICE_TYPE, service_type,
+                                           -1);
+                       g_free (markup);
+
+next:
+                       if (!aliases || !aliases[0])
+                               break;
+                       is_alias = TRUE;
+                       service_type = aliases[0];
+                       aliases++;
+               }
 
                if (nm_vpn_editor_plugin_get_capabilities (plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT)
                        import_supported = TRUE;
@@ -389,8 +427,7 @@ new_connection_dialog_full (GtkWindow *parent_window,
        GtkTreeIter iter;
        int response;
        PageNewConnectionFunc new_func = NULL;
-       NMVpnEditorPlugin *plugin = NULL;
-       char *vpn_type = NULL;
+       gs_free char *vpn_service_type = NULL;
        GError *error = NULL;
 
        /* load GUI */
@@ -425,24 +462,17 @@ new_connection_dialog_full (GtkWindow *parent_window,
                gtk_combo_box_get_active_iter (combo, &iter);
                gtk_tree_model_get (gtk_combo_box_get_model (combo), &iter,
                                    COL_NEW_FUNC, &new_func,
-                                   COL_VPN_PLUGIN, &plugin,
+                                   COL_VPN_SERVICE_TYPE, &vpn_service_type,
                                    -1);
-
-               if (plugin) {
-                       g_object_get (G_OBJECT (plugin), NM_VPN_EDITOR_PLUGIN_SERVICE, &vpn_type, NULL);
-                       g_object_unref (plugin);
-               }
        }
 
        gtk_widget_destroy (GTK_WIDGET (type_dialog));
        g_object_unref (gui);
 
        if (new_func)
-               new_connection_of_type (parent_window, vpn_type, client, new_func, result_func, user_data);
+               new_connection_of_type (parent_window, vpn_service_type, client, new_func, result_func, 
user_data);
        else
                result_func (NULL, user_data);
-
-       g_free (vpn_type);
 }
 
 typedef struct {
diff --git a/src/connection-editor/vpn-helpers.c b/src/connection-editor/vpn-helpers.c
index 0fd3f98..4a875ed 100644
--- a/src/connection-editor/vpn-helpers.c
+++ b/src/connection-editor/vpn-helpers.c
@@ -337,3 +337,4 @@ vpn_supports_ipv6 (NMConnection *connection)
        capabilities = nm_vpn_editor_plugin_get_capabilities (plugin);
        return (capabilities & NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6) != 0;
 }
+


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]