network-manager-applet r1244 - in trunk: . po src/connection-editor src/marshallers



Author: dcbw
Date: Fri Apr  3 13:28:12 2009
New Revision: 1244
URL: http://svn.gnome.org/viewvc/network-manager-applet?rev=1244&view=rev

Log:
2009-04-03  Dan Williams  <dcbw redhat com>

	* Ensure PolicyKit autorization before editing system connections, and
		request secrets from the system settings service for system connections.
		This requires splitting each CEPage subclass's *_new() method into
		two parts, the first doing minimal setup, and the second filling in
		the UI with details from the backing NMConnection.  Between the first
		and second parts, if required, secrets are requested from the system
		settings service using PolicyKit.  As a bonus, actually handle errors
		instead of dropping them on the floor.



Added:
   trunk/src/connection-editor/polkit-helpers.c
   trunk/src/connection-editor/polkit-helpers.h
Modified:
   trunk/ChangeLog
   trunk/po/POTFILES.in
   trunk/src/connection-editor/Makefile.am
   trunk/src/connection-editor/ce-page.c
   trunk/src/connection-editor/ce-page.h
   trunk/src/connection-editor/nm-connection-editor.c
   trunk/src/connection-editor/nm-connection-editor.glade
   trunk/src/connection-editor/nm-connection-editor.h
   trunk/src/connection-editor/nm-connection-list.c
   trunk/src/connection-editor/nm-connection-list.h
   trunk/src/connection-editor/page-dsl.c
   trunk/src/connection-editor/page-dsl.h
   trunk/src/connection-editor/page-ip4.c
   trunk/src/connection-editor/page-ip4.h
   trunk/src/connection-editor/page-mobile.c
   trunk/src/connection-editor/page-mobile.h
   trunk/src/connection-editor/page-ppp.c
   trunk/src/connection-editor/page-ppp.h
   trunk/src/connection-editor/page-vpn.c
   trunk/src/connection-editor/page-vpn.h
   trunk/src/connection-editor/page-wired-security.c
   trunk/src/connection-editor/page-wired-security.h
   trunk/src/connection-editor/page-wired.c
   trunk/src/connection-editor/page-wired.h
   trunk/src/connection-editor/page-wireless-security.c
   trunk/src/connection-editor/page-wireless-security.h
   trunk/src/connection-editor/page-wireless.c
   trunk/src/connection-editor/page-wireless.h
   trunk/src/marshallers/nma-marshal.list

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Fri Apr  3 13:28:12 2009
@@ -33,6 +33,7 @@
 src/connection-editor/page-wired-security.c
 src/connection-editor/page-wireless.c
 src/connection-editor/page-wireless-security.c
+src/connection-editor/polkit-helpers.c
 src/connection-editor/nm-connection-editor.c
 src/connection-editor/nm-connection-editor.glade
 src/connection-editor/nm-connection-list.c

Modified: trunk/src/connection-editor/Makefile.am
==============================================================================
--- trunk/src/connection-editor/Makefile.am	(original)
+++ trunk/src/connection-editor/Makefile.am	Fri Apr  3 13:28:12 2009
@@ -2,20 +2,21 @@
 
 bin_PROGRAMS = nm-connection-editor
 
-nm_connection_editor_CPPFLAGS =			\
-	$(NMA_CFLAGS)				\
-	-DICONDIR=\""$(datadir)/icons"\"	\
-	-DGLADEDIR=\""$(gladedir)"\"		\
-	-DBINDIR=\""$(bindir)"\"		\
-	-DSYSCONFDIR=\""$(sysconfdir)"\"	\
-	-DLIBDIR=\""$(libdir)"\"	\
-	-DNMALOCALEDIR=\"$(datadir)/locale\"	\
-	$(DBUS_CFLAGS)				\
+nm_connection_editor_CPPFLAGS = \
+	$(NMA_CFLAGS) \
+	-DICONDIR=\""$(datadir)/icons"\" \
+	-DGLADEDIR=\""$(gladedir)"\" \
+	-DBINDIR=\""$(bindir)"\" \
+	-DSYSCONFDIR=\""$(sysconfdir)"\" \
+	-DLIBDIR=\""$(libdir)"\" \
+	-DNMALOCALEDIR=\"$(datadir)/locale\" \
+	$(DBUS_CFLAGS) \
 	$(POLKIT_CFLAGS) \
-	$(DISABLE_DEPRECATED)			\
-	-I${top_srcdir}/src/gconf-helpers  \
+	$(DISABLE_DEPRECATED) \
+	-I${top_srcdir}/src/gconf-helpers \
 	-I${top_srcdir}/src/utils \
 	-I${top_srcdir}/src/wireless-security \
+	-I${top_builddir}/src/marshallers \
 	$(NULL)
 
 if NO_POLKIT_GNOME
@@ -56,7 +57,9 @@
 	ip4-routes-dialog.h \
 	ip4-routes-dialog.c \
 	ppp-auth-methods-dialog.c \
-	ppp-auth-methods-dialog.h
+	ppp-auth-methods-dialog.h \
+	polkit-helpers.c \
+	polkit-helpers.h
 
 nm-connection-editor-service-glue.h: $(top_srcdir)/src/connection-editor/nm-connection-editor-service.xml
 	dbus-binding-tool --prefix=nm_connection_editor_service --mode=glib-server --output=$@ $<
@@ -65,6 +68,7 @@
 	$(top_builddir)/src/gconf-helpers/libgconf-helpers.la \
 	${top_builddir}/src/wireless-security/libwireless-security.la \
 	${top_builddir}/src/utils/libutils.la \
+	${top_builddir}/src/marshallers/libmarshallers.la \
 	$(NMA_LIBS) \
 	$(POLKIT_LIBS)
 

Modified: trunk/src/connection-editor/ce-page.c
==============================================================================
--- trunk/src/connection-editor/ce-page.c	(original)
+++ trunk/src/connection-editor/ce-page.c	Fri Apr  3 13:28:12 2009
@@ -17,7 +17,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2008 Red Hat, Inc.
+ * (C) Copyright 2008 - 2009 Red Hat, Inc.
  */
 
 #include <net/ethernet.h>
@@ -28,12 +28,30 @@
 #include <glib/gi18n.h>
 
 #include "ce-page.h"
+#include "nma-marshal.h"
 #include "utils.h"
+#include "polkit-helpers.h"
+
+#define DBUS_TYPE_G_ARRAY_OF_STRING         (dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING))
+#define DBUS_TYPE_G_MAP_OF_VARIANT          (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE))
+#define DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT   (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT))
+
+static gboolean internal_request_secrets (CEPage *self, GError **error);
 
 G_DEFINE_ABSTRACT_TYPE (CEPage, ce_page, G_TYPE_OBJECT)
 
 enum {
+	PROP_0,
+	PROP_CONNECTION,
+	PROP_INITIALIZED,
+	PROP_PARENT_WINDOW,
+
+	LAST_PROP
+};
+
+enum {
 	CHANGED,
+	INITIALIZED,
 
 	LAST_SIGNAL
 };
@@ -152,9 +170,158 @@
 }
 
 static void
+emit_initialized (CEPage *self, GError *error)
+{
+	self->initialized = TRUE;
+	g_signal_emit (self, signals[INITIALIZED], 0, NULL, error);
+}
+
+static void
+try_secrets_again (PolKitAction *action,
+                   gboolean gained_privilege,
+                   GError *error,
+                   gpointer user_data)
+{
+	CEPage *self = user_data;
+	GError *real_error = NULL;
+
+	if (error) {
+		emit_initialized (self, error);
+		return;
+	}
+
+	if (gained_privilege) {
+		/* Yay! Got privilege, try again */
+		internal_request_secrets (self, &real_error);
+	} else if (!error) {
+		/* Sometimes PK screws up and won't return an error even if
+		 * the operation failed.
+		 */
+		g_set_error (&real_error, 0, 0, "%s",
+		             _("Insufficient privileges or unknown error retrieving system connection secrets."));
+	}
+
+	if (real_error)
+		emit_initialized (self, real_error);
+	g_clear_error (&real_error);
+}
+
+static void
+get_secrets_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
+{
+	CEPage *self = user_data;
+	GError *error = NULL;
+	GHashTable *settings = NULL, *setting_hash;
+	gboolean do_signal = TRUE;
+
+	if (!dbus_g_proxy_end_call (proxy, call, &error,
+	                            DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, &settings,
+	                            G_TYPE_INVALID)) {
+		if (pk_helper_is_permission_denied_error (error)) {
+			/* If permission was denied, try to authenticate */
+			g_clear_error (&error);
+			if (pk_helper_obtain_auth (error, self->parent_window, try_secrets_again, self, &error))
+				do_signal = FALSE; /* 'secrets' signal will happen after auth result */
+		}
+	} else {
+		/* Update the connection with the new secrets */
+		setting_hash = g_hash_table_lookup (settings, self->setting_name);
+		if (setting_hash) {
+			if (!nm_connection_update_secrets (self->connection,
+			                                   self->setting_name,
+			                                   setting_hash,
+			                                   &error)) {
+				if (!error) {
+					g_set_error (&error, 0, 0, "%s",
+					             _("Failed to update connection secrets due to an unknown error."));
+				}
+			}
+		}
+		g_hash_table_destroy (settings);
+	}
+
+	if (do_signal)
+		emit_initialized (self, error);
+}
+
+static gboolean
+internal_request_secrets (CEPage *self, GError **error)
+{
+	DBusGProxyCall *call;
+	GPtrArray *hints = NULL;
+
+	g_return_val_if_fail (self != NULL, FALSE);
+	g_return_val_if_fail (self->proxy != NULL, FALSE);
+	g_return_val_if_fail (self->setting_name != NULL, FALSE);
+
+	hints = g_ptr_array_new ();
+	call = dbus_g_proxy_begin_call_with_timeout (self->proxy, "GetSecrets",
+	                                             get_secrets_cb, self, NULL,
+	                                             10000,
+	                                             G_TYPE_STRING, self->setting_name,
+	                                             DBUS_TYPE_G_ARRAY_OF_STRING, hints,
+	                                             G_TYPE_BOOLEAN, FALSE,
+	                                             G_TYPE_INVALID);
+	g_ptr_array_free (hints, TRUE);
+
+	if (!call) {
+		g_set_error (error, 0, 0, "%s", _("Could not request secrets from the system settings service."));
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+gboolean
+ce_page_initialize (CEPage *self,
+                    const char *setting_name,
+                    GError **error)
+{
+	DBusGConnection *g_connection;
+	gboolean success = FALSE;
+	NMConnectionScope scope;
+
+	g_return_val_if_fail (self != NULL, FALSE);
+	g_return_val_if_fail (self->connection != NULL, FALSE);
+
+	/* Don't need to request secrets from user connections or from
+	 * settings which are known to not require secrets.
+	 */
+	scope = nm_connection_get_scope (self->connection);
+	if (!setting_name || (scope != NM_CONNECTION_SCOPE_SYSTEM)) {
+		emit_initialized (self, NULL);
+		return TRUE;
+	}
+
+	g_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, error);
+	if (!g_connection) {
+		g_set_error (error, 0, 0, "%s", _("Could not connect to D-Bus to request connection secrets."));
+		return FALSE;
+	}
+
+	if (self->setting_name)
+		g_free (self->setting_name);
+	self->setting_name = g_strdup (setting_name);
+
+	self->proxy = dbus_g_proxy_new_for_name (g_connection,
+	                                         NM_DBUS_SERVICE_SYSTEM_SETTINGS,
+	                                         nm_connection_get_path (self->connection),
+	                                         NM_DBUS_IFACE_SETTINGS_CONNECTION_SECRETS);
+	if (!self->proxy) {
+		g_set_error (error, 0, 0, "%s", _("Could not create D-Bus proxy for connection secrets."));
+		goto out;
+	}
+
+	success = internal_request_secrets (self, error);
+
+out:
+	dbus_g_connection_unref (g_connection);
+	return success;
+}
+
+static void
 ce_page_init (CEPage *self)
 {
-	self->disposed = FALSE;
 }
 
 static void
@@ -173,6 +340,12 @@
 	if (self->xml)
 		g_object_unref (self->xml);
 
+	if (self->proxy)
+		g_object_unref (self->proxy);
+
+	if (self->connection)
+		g_object_unref (self->connection);
+
 	G_OBJECT_CLASS (ce_page_parent_class)->dispose (object);
 }
 
@@ -181,8 +354,8 @@
 {
 	CEPage *self = CE_PAGE (object);
 
-	if (self->title)
-		g_free (self->title);
+	g_free (self->title);
+	g_free (self->setting_name);
 
 	G_OBJECT_CLASS (ce_page_parent_class)->finalize (object);
 }
@@ -203,6 +376,14 @@
 	return self->title;
 }
 
+gboolean
+ce_page_get_initialized (CEPage *self)
+{
+	g_return_val_if_fail (CE_IS_PAGE (self), FALSE);
+
+	return self->initialized;
+}
+
 void
 ce_page_changed (CEPage *self)
 {
@@ -212,21 +393,96 @@
 }
 
 static void
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
+{
+	CEPage *self = CE_PAGE (object);
+
+	switch (prop_id) {
+	case PROP_CONNECTION:
+		g_value_set_object (value, self->connection);
+		break;
+	case PROP_INITIALIZED:
+		g_value_set_boolean (value, self->initialized);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	CEPage *self = CE_PAGE (object);
+
+	switch (prop_id) {
+	case PROP_CONNECTION:
+		if (self->connection)
+			g_object_unref (self->connection);
+		self->connection = g_value_dup_object (value);
+		break;
+	case PROP_PARENT_WINDOW:
+		self->parent_window = g_value_get_pointer (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
 ce_page_class_init (CEPageClass *page_class)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (page_class);
 
 	/* virtual methods */
-	object_class->dispose     = dispose;
-	object_class->finalize    = finalize;
+	object_class->dispose      = dispose;
+	object_class->finalize     = finalize;
+	object_class->get_property = get_property;
+	object_class->set_property = set_property;
+
+	/* Properties */
+	g_object_class_install_property
+		(object_class, PROP_CONNECTION,
+		 g_param_spec_object (CE_PAGE_CONNECTION,
+		                      "Connection",
+		                      "Connection",
+		                      NM_TYPE_CONNECTION,
+		                      G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property
+		(object_class, PROP_INITIALIZED,
+		 g_param_spec_boolean (CE_PAGE_INITIALIZED,
+		                       "Initialized",
+		                       "Initialized",
+		                       FALSE,
+		                       G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_PARENT_WINDOW,
+		 g_param_spec_pointer (CE_PAGE_PARENT_WINDOW,
+		                       "Parent window",
+		                       "Parent window",
+		                       G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
 
 	/* Signals */
 	signals[CHANGED] = 
 		g_signal_new ("changed",
-					  G_OBJECT_CLASS_TYPE (object_class),
-					  G_SIGNAL_RUN_FIRST,
-					  G_STRUCT_OFFSET (CEPageClass, changed),
-					  NULL, NULL,
-					  g_cclosure_marshal_VOID__VOID,
-					  G_TYPE_NONE, 0);
+	                      G_OBJECT_CLASS_TYPE (object_class),
+	                      G_SIGNAL_RUN_FIRST,
+	                      G_STRUCT_OFFSET (CEPageClass, changed),
+	                      NULL, NULL,
+	                      g_cclosure_marshal_VOID__VOID,
+	                      G_TYPE_NONE, 0);
+
+	signals[INITIALIZED] = 
+		g_signal_new ("initialized",
+	                      G_OBJECT_CLASS_TYPE (object_class),
+	                      G_SIGNAL_RUN_FIRST,
+	                      G_STRUCT_OFFSET (CEPageClass, initialized),
+	                      NULL, NULL,
+	                      nma_marshal_VOID__POINTER_POINTER,
+	                      G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
 }

Modified: trunk/src/connection-editor/ce-page.h
==============================================================================
--- trunk/src/connection-editor/ce-page.h	(original)
+++ trunk/src/connection-editor/ce-page.h	Fri Apr  3 13:28:12 2009
@@ -29,6 +29,7 @@
 #include <gtk/gtk.h>
 #include <glade/glade.h>
 
+#include <dbus/dbus-glib.h>
 #include <nm-connection.h>
 
 #define CE_TYPE_PAGE            (ce_page_get_type ())
@@ -38,13 +39,25 @@
 #define CE_IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), CE_TYPE_PAGE))
 #define CE_PAGE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), CE_TYPE_PAGE, CEPageClass))
 
+#define CE_PAGE_CONNECTION "connection"
+#define CE_PAGE_INITIALIZED "initialized"
+#define CE_PAGE_PARENT_WINDOW "parent-window"
+
 typedef struct {
 	GObject parent;
 
+	gboolean initialized;
 	GladeXML *xml;
 	GtkWidget *page;
 	char *title;
 
+	DBusGProxy *proxy;
+	gulong secrets_done_validate;
+
+	char *setting_name;
+	NMConnection *connection;
+	GtkWindow *parent_window;
+
 	gboolean disposed;
 } CEPage;
 
@@ -52,12 +65,17 @@
 	GObjectClass parent;
 
 	/* Virtual functions */
-	gboolean    (*validate)            (CEPage *self, NMConnection *connection, GError **error);
+	gboolean    (*validate)    (CEPage *self, NMConnection *connection, GError **error);
 
 	/* Signals */
-	void        (*changed)             (CEPage *self);
+	void        (*changed)     (CEPage *self);
+	void        (*initialized) (CEPage *self, GHashTable *secrets, GError *error);
 } CEPageClass;
 
+
+typedef CEPage* (*CEPageNewFunc)(NMConnection *connection, GtkWindow *parent, GError **error);
+
+
 GType ce_page_get_type (void);
 
 GtkWidget *  ce_page_get_page (CEPage *self);
@@ -76,5 +94,11 @@
 
 int ce_get_property_default (NMSetting *setting, const char *property_name);
 
+gboolean ce_page_initialize (CEPage *self,
+                             const char *setting_name,
+                             GError **error);
+
+gboolean ce_page_get_initialized (CEPage *self);
+
 #endif  /* __CE_PAGE_H__ */
 

Modified: trunk/src/connection-editor/nm-connection-editor.c
==============================================================================
--- trunk/src/connection-editor/nm-connection-editor.c	(original)
+++ trunk/src/connection-editor/nm-connection-editor.c	Fri Apr  3 13:28:12 2009
@@ -61,6 +61,7 @@
 
 #include "nm-connection-editor.h"
 #include "gconf-helpers.h"
+#include "nma-marshal.h"
 
 #include "ce-page.h"
 #include "page-wired.h"
@@ -72,6 +73,7 @@
 #include "page-mobile.h"
 #include "page-ppp.h"
 #include "page-vpn.h"
+#include "polkit-helpers.h"
 
 G_DEFINE_TYPE (NMConnectionEditor, nm_connection_editor, G_TYPE_OBJECT)
 
@@ -82,8 +84,9 @@
 
 static guint editor_signals[EDITOR_LAST_SIGNAL] = { 0 };
 
-static void nm_connection_editor_set_connection (NMConnectionEditor *editor,
-                                                 NMConnection *connection);
+static gboolean nm_connection_editor_set_connection (NMConnectionEditor *editor,
+                                                     NMConnection *connection,
+                                                     GError **error);
 
 static void
 nm_connection_editor_update_title (NMConnectionEditor *editor)
@@ -396,28 +399,34 @@
 	/* Signals */
 	editor_signals[EDITOR_DONE] =
 		g_signal_new ("done",
-					  G_OBJECT_CLASS_TYPE (object_class),
-					  G_SIGNAL_RUN_FIRST,
-					  G_STRUCT_OFFSET (NMConnectionEditorClass, done),
-					  NULL, NULL,
-					  g_cclosure_marshal_VOID__INT,
-					  G_TYPE_NONE, 1, G_TYPE_INT);
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              G_STRUCT_OFFSET (NMConnectionEditorClass, done),
+		              NULL, NULL,
+		              nma_marshal_VOID__INT_POINTER,
+		              G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_POINTER);
 }
 
 NMConnectionEditor *
 nm_connection_editor_new (NMConnection *connection,
-                          gboolean system_settings_can_modify)
+                          gboolean system_settings_can_modify,
+                          GError **error)
 {
 	NMConnectionEditor *editor;
 
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	editor = g_object_new (NM_TYPE_CONNECTION_EDITOR, NULL);
-	if (!editor)
+	if (!editor) {
+		g_set_error (error, 0, 0, "%s", _("Error creating connection editor dialog."));
 		return NULL;
+	}
 
 	editor->system_settings_can_modify = system_settings_can_modify;
-	nm_connection_editor_set_connection (editor, connection);
+	if (!nm_connection_editor_set_connection (editor, connection, error)) {
+		g_object_unref (editor);
+		return NULL;
+	}
 
 	return editor;
 }
@@ -472,43 +481,92 @@
 	connection_editor_validate (editor);
 }
 
+static gboolean
+idle_validate (gpointer user_data)
+{
+	connection_editor_validate (NM_CONNECTION_EDITOR (user_data));
+	return FALSE;
+}
+
+static void
+recheck_initialization (NMConnectionEditor *editor)
+{
+	GSList *iter;
+
+	/* Check if all pages are initialized; if not, desensitize the editor */
+	for (iter = editor->pages; iter; iter = g_slist_next (iter)) {
+		if (!ce_page_get_initialized (CE_PAGE (iter->data))) {
+			set_editor_sensitivity (editor, FALSE);
+			return;
+		}
+	}
+
+	populate_connection_ui (editor);
+	update_sensitivity (editor, POLKIT_RESULT_UNKNOWN);
+
+	/* Validate the connection from an idle handler to ensure that stuff like
+	 * GtkFileChoosers have had a chance to asynchronously find their files.
+	 */
+	g_idle_add (idle_validate, editor);
+}
+
 static void
-add_page (NMConnectionEditor *editor, CEPage *page)
+page_initialized (CEPage *page, gpointer unused, GError *error, gpointer user_data)
+{
+	NMConnectionEditor *editor = NM_CONNECTION_EDITOR (user_data);
+
+	if (error) {
+		gtk_widget_hide (editor->window);
+		g_signal_emit (editor, editor_signals[EDITOR_DONE], 0, GTK_RESPONSE_NONE, error);
+		return;
+	}
+
+	recheck_initialization (editor);
+}
+
+static gboolean
+add_page (NMConnectionEditor *editor,
+          CEPageNewFunc func,
+          NMConnection *connection,
+          GError **error)
 {
+	CEPage *page;
 	GtkWidget *widget;
 	GtkWidget *notebook;
 	GtkWidget *label;
 
-	g_return_if_fail (editor != NULL);
-	g_return_if_fail (page != NULL);
+	g_return_val_if_fail (editor != NULL, FALSE);
+	g_return_val_if_fail (func != NULL, FALSE);
+	g_return_val_if_fail (connection != NULL, FALSE);
+
+	page = (*func) (connection, GTK_WINDOW (editor->window), error);
+	if (!page)
+		return FALSE;
 
 	notebook = glade_xml_get_widget (editor->xml, "notebook");
 	label = gtk_label_new (ce_page_get_title (page));
 	widget = ce_page_get_page (page);
 	gtk_notebook_append_page (GTK_NOTEBOOK (notebook), widget, label);
 
-	g_signal_connect (page, "changed",
-				   G_CALLBACK (page_changed),
-				   editor);
-
 	editor->pages = g_slist_append (editor->pages, page);
-}
 
-static gboolean
-idle_validate (gpointer user_data)
-{
-	connection_editor_validate (NM_CONNECTION_EDITOR (user_data));
-	return FALSE;
+	g_signal_connect (page, "changed", G_CALLBACK (page_changed), editor);
+	g_signal_connect (page, "initialized", G_CALLBACK (page_initialized), editor);
+
+	return TRUE;
 }
 
-static void
-nm_connection_editor_set_connection (NMConnectionEditor *editor, NMConnection *connection)
+static gboolean
+nm_connection_editor_set_connection (NMConnectionEditor *editor,
+                                     NMConnection *connection,
+                                     GError **error)
 {
 	NMSettingConnection *s_con;
 	const char *connection_type;
+	gboolean success = FALSE;
 
-	g_return_if_fail (NM_IS_CONNECTION_EDITOR (editor));
-	g_return_if_fail (NM_IS_CONNECTION (connection));
+	g_return_val_if_fail (NM_IS_CONNECTION_EDITOR (editor), FALSE);
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
 
 	/* clean previous connection */
 	if (editor->connection)
@@ -523,37 +581,51 @@
 
 	connection_type = nm_setting_connection_get_connection_type (s_con);
 	if (!strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME)) {
-		add_page (editor, CE_PAGE (ce_page_wired_new (editor->connection)));
-		add_page (editor, CE_PAGE (ce_page_wired_security_new (editor->connection)));
-		add_page (editor, CE_PAGE (ce_page_ip4_new (editor->connection)));
+		if (!add_page (editor, ce_page_wired_new, connection, error))
+			goto out;
+		if (!add_page (editor, ce_page_wired_security_new, connection, error))
+			goto out;
+		if (!add_page (editor, ce_page_ip4_new, connection, error))
+			goto out;
 	} else if (!strcmp (connection_type, NM_SETTING_WIRELESS_SETTING_NAME)) {
-		add_page (editor, CE_PAGE (ce_page_wireless_new (editor->connection)));
-		add_page (editor, CE_PAGE (ce_page_wireless_security_new (editor->connection)));
-		add_page (editor, CE_PAGE (ce_page_ip4_new (editor->connection)));
+		if (!add_page (editor, ce_page_wireless_new, connection, error))
+			goto out;
+		if (!add_page (editor, ce_page_wireless_security_new, connection, error))
+			goto out;
+		if (!add_page (editor, ce_page_ip4_new, connection, error))
+			goto out;
 	} else if (!strcmp (connection_type, NM_SETTING_VPN_SETTING_NAME)) {
-		add_page (editor, CE_PAGE (ce_page_vpn_new (editor->connection)));
-		add_page (editor, CE_PAGE (ce_page_ip4_new (editor->connection)));
+		if (!add_page (editor, ce_page_vpn_new, connection, error))
+			goto out;
+		if (!add_page (editor, ce_page_ip4_new, connection, error))
+			goto out;
 	} else if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) {
-		add_page (editor, CE_PAGE (ce_page_dsl_new (editor->connection)));
-		add_page (editor, CE_PAGE (ce_page_wired_new (editor->connection)));
-		add_page (editor, CE_PAGE (ce_page_ppp_new (editor->connection)));
-		add_page (editor, CE_PAGE (ce_page_ip4_new (editor->connection)));
+		if (!add_page (editor, ce_page_dsl_new, connection, error))
+			goto out;
+		if (!add_page (editor, ce_page_wired_new, connection, error))
+			goto out;
+		if (!add_page (editor, ce_page_ppp_new, connection, error))
+			goto out;
+		if (!add_page (editor, ce_page_ip4_new, connection, error))
+			goto out;
 	} else if (!strcmp (connection_type, NM_SETTING_GSM_SETTING_NAME) || 
-			 !strcmp (connection_type, NM_SETTING_CDMA_SETTING_NAME)) {
-		add_page (editor, CE_PAGE (ce_page_mobile_new (editor->connection)));
-		add_page (editor, CE_PAGE (ce_page_ppp_new (editor->connection)));
-		add_page (editor, CE_PAGE (ce_page_ip4_new (editor->connection)));
+	           !strcmp (connection_type, NM_SETTING_CDMA_SETTING_NAME)) {
+		if (!add_page (editor, ce_page_mobile_new, connection, error))
+			goto out;
+		if (!add_page (editor, ce_page_ppp_new, connection, error))
+			goto out;
+		if (!add_page (editor, ce_page_ip4_new, connection, error))
+			goto out;
 	} else {
 		g_warning ("Unhandled setting type '%s'", connection_type);
 	}
 
 	/* set the UI */
-	populate_connection_ui (editor);
+	recheck_initialization (editor);
+	success = TRUE;
 
-	/* Validate the connection from an idle handler to ensure that stuff like
-	 * GtkFileChoosers have had a chance to asynchronously find their files.
-	 */
-	g_idle_add (idle_validate, editor);
+out:
+	return success;
 }
 
 void
@@ -570,7 +642,7 @@
 	NMConnectionEditor *self = NM_CONNECTION_EDITOR (user_data);
 
 	gtk_widget_hide (widget);
-	g_signal_emit (self, editor_signals[EDITOR_DONE], 0, GTK_RESPONSE_CANCEL);
+	g_signal_emit (self, editor_signals[EDITOR_DONE], 0, GTK_RESPONSE_CANCEL, NULL);
 }
 
 static void
@@ -585,7 +657,7 @@
 	NMConnectionEditor *self = NM_CONNECTION_EDITOR (user_data);
 
 	gtk_widget_hide (widget);
-	g_signal_emit (self, editor_signals[EDITOR_DONE], 0, GTK_RESPONSE_OK);
+	g_signal_emit (self, editor_signals[EDITOR_DONE], 0, GTK_RESPONSE_OK, NULL);
 }
 
 void

Modified: trunk/src/connection-editor/nm-connection-editor.glade
==============================================================================
--- trunk/src/connection-editor/nm-connection-editor.glade	(original)
+++ trunk/src/connection-editor/nm-connection-editor.glade	Fri Apr  3 13:28:12 2009
@@ -43,7 +43,7 @@
                   </widget>
                 </child>
                 <child>
-                  <widget class="GtkVButtonBox" id="vbuttonbox2">
+                  <widget class="GtkVButtonBox" id="wired_button_box">
                     <property name="visible">True</property>
                     <property name="spacing">6</property>
                     <property name="layout_style">GTK_BUTTONBOX_START</property>
@@ -58,32 +58,10 @@
                       </widget>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="wired_edit">
-                        <property name="visible">True</property>
-                        <property name="sensitive">False</property>
-                        <property name="can_focus">True</property>
-                        <property name="can_default">True</property>
-                        <property name="label">gtk-edit</property>
-                        <property name="use_stock">True</property>
-                        <property name="response_id">0</property>
-                      </widget>
-                      <packing>
-                        <property name="position">1</property>
-                      </packing>
+                      <placeholder/>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="wired_delete">
-                        <property name="visible">True</property>
-                        <property name="sensitive">False</property>
-                        <property name="can_focus">True</property>
-                        <property name="can_default">True</property>
-                        <property name="label">gtk-delete</property>
-                        <property name="use_stock">True</property>
-                        <property name="response_id">0</property>
-                      </widget>
-                      <packing>
-                        <property name="position">2</property>
-                      </packing>
+                      <placeholder/>
                     </child>
                   </widget>
                   <packing>
@@ -126,7 +104,7 @@
                   </widget>
                 </child>
                 <child>
-                  <widget class="GtkVButtonBox" id="vbuttonbox3">
+                  <widget class="GtkVButtonBox" id="wireless_button_box">
                     <property name="visible">True</property>
                     <property name="spacing">6</property>
                     <property name="layout_style">GTK_BUTTONBOX_START</property>
@@ -141,32 +119,10 @@
                       </widget>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="wireless_edit">
-                        <property name="visible">True</property>
-                        <property name="sensitive">False</property>
-                        <property name="can_focus">True</property>
-                        <property name="can_default">True</property>
-                        <property name="label">gtk-edit</property>
-                        <property name="use_stock">True</property>
-                        <property name="response_id">0</property>
-                      </widget>
-                      <packing>
-                        <property name="position">1</property>
-                      </packing>
+                      <placeholder/>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="wireless_delete">
-                        <property name="visible">True</property>
-                        <property name="sensitive">False</property>
-                        <property name="can_focus">True</property>
-                        <property name="can_default">True</property>
-                        <property name="label">gtk-delete</property>
-                        <property name="use_stock">True</property>
-                        <property name="response_id">0</property>
-                      </widget>
-                      <packing>
-                        <property name="position">2</property>
-                      </packing>
+                      <placeholder/>
                     </child>
                   </widget>
                   <packing>
@@ -213,7 +169,7 @@
                   </widget>
                 </child>
                 <child>
-                  <widget class="GtkVButtonBox" id="vbuttonbox4">
+                  <widget class="GtkVButtonBox" id="wwan_button_box">
                     <property name="visible">True</property>
                     <property name="spacing">6</property>
                     <property name="layout_style">GTK_BUTTONBOX_START</property>
@@ -228,32 +184,10 @@
                       </widget>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="wwan_edit">
-                        <property name="visible">True</property>
-                        <property name="sensitive">False</property>
-                        <property name="can_focus">True</property>
-                        <property name="can_default">True</property>
-                        <property name="label">gtk-edit</property>
-                        <property name="use_stock">True</property>
-                        <property name="response_id">0</property>
-                      </widget>
-                      <packing>
-                        <property name="position">1</property>
-                      </packing>
+                      <placeholder/>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="wwan_delete">
-                        <property name="visible">True</property>
-                        <property name="sensitive">False</property>
-                        <property name="can_focus">True</property>
-                        <property name="can_default">True</property>
-                        <property name="label">gtk-delete</property>
-                        <property name="use_stock">True</property>
-                        <property name="response_id">0</property>
-                      </widget>
-                      <packing>
-                        <property name="position">2</property>
-                      </packing>
+                      <placeholder/>
                     </child>
                   </widget>
                   <packing>
@@ -300,46 +234,33 @@
                   </widget>
                 </child>
                 <child>
-                  <widget class="GtkVButtonBox" id="vbuttonbox5">
+                  <widget class="GtkVBox" id="vbox1">
                     <property name="visible">True</property>
                     <property name="spacing">6</property>
-                    <property name="layout_style">GTK_BUTTONBOX_START</property>
-                    <child>
-                      <widget class="GtkButton" id="vpn_add">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="can_default">True</property>
-                        <property name="label">gtk-add</property>
-                        <property name="use_stock">True</property>
-                        <property name="response_id">0</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkButton" id="vpn_edit">
-                        <property name="visible">True</property>
-                        <property name="sensitive">False</property>
-                        <property name="can_focus">True</property>
-                        <property name="can_default">True</property>
-                        <property name="label">gtk-edit</property>
-                        <property name="use_stock">True</property>
-                        <property name="response_id">0</property>
-                      </widget>
-                      <packing>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
                     <child>
-                      <widget class="GtkButton" id="vpn_delete">
+                      <widget class="GtkVButtonBox" id="vpn_button_box">
                         <property name="visible">True</property>
-                        <property name="sensitive">False</property>
-                        <property name="can_focus">True</property>
-                        <property name="can_default">True</property>
-                        <property name="label">gtk-delete</property>
-                        <property name="use_stock">True</property>
-                        <property name="response_id">0</property>
+                        <property name="spacing">6</property>
+                        <property name="layout_style">GTK_BUTTONBOX_START</property>
+                        <child>
+                          <widget class="GtkButton" id="vpn_add">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="can_default">True</property>
+                            <property name="label">gtk-add</property>
+                            <property name="use_stock">True</property>
+                            <property name="response_id">0</property>
+                          </widget>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
                       </widget>
                       <packing>
-                        <property name="position">2</property>
+                        <property name="expand">False</property>
                       </packing>
                     </child>
                     <child>
@@ -349,38 +270,47 @@
                       <packing>
                         <property name="expand">False</property>
                         <property name="fill">False</property>
-                        <property name="position">3</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <widget class="GtkButton" id="vpn_import">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="label" translatable="yes">_Import</property>
-                        <property name="use_underline">True</property>
-                        <property name="response_id">0</property>
-                      </widget>
-                      <packing>
-                        <property name="position">4</property>
+                        <property name="position">1</property>
                       </packing>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="vpn_export">
+                      <widget class="GtkVButtonBox" id="vpn_ix_button_box">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="label" translatable="yes">E_xport</property>
-                        <property name="use_underline">True</property>
-                        <property name="response_id">0</property>
+                        <property name="spacing">6</property>
+                        <property name="layout_style">GTK_BUTTONBOX_START</property>
+                        <child>
+                          <widget class="GtkButton" id="vpn_import">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="label" translatable="yes">_Import</property>
+                            <property name="use_underline">True</property>
+                            <property name="response_id">0</property>
+                          </widget>
+                        </child>
+                        <child>
+                          <widget class="GtkButton" id="vpn_export">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="label" translatable="yes">E_xport</property>
+                            <property name="use_underline">True</property>
+                            <property name="response_id">0</property>
+                          </widget>
+                          <packing>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
                       </widget>
                       <packing>
-                        <property name="position">5</property>
+                        <property name="expand">False</property>
+                        <property name="position">2</property>
                       </packing>
                     </child>
                   </widget>
                   <packing>
                     <property name="expand">False</property>
+                    <property name="padding">6</property>
                     <property name="position">1</property>
                   </packing>
                 </child>
@@ -423,7 +353,7 @@
                   </widget>
                 </child>
                 <child>
-                  <widget class="GtkVButtonBox" id="vbuttonbox6">
+                  <widget class="GtkVButtonBox" id="dsl_button_box">
                     <property name="visible">True</property>
                     <property name="spacing">6</property>
                     <property name="layout_style">GTK_BUTTONBOX_START</property>
@@ -438,32 +368,10 @@
                       </widget>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="dsl_edit">
-                        <property name="visible">True</property>
-                        <property name="sensitive">False</property>
-                        <property name="can_focus">True</property>
-                        <property name="can_default">True</property>
-                        <property name="label">gtk-edit</property>
-                        <property name="use_stock">True</property>
-                        <property name="response_id">0</property>
-                      </widget>
-                      <packing>
-                        <property name="position">1</property>
-                      </packing>
+                      <placeholder/>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="dsl_delete">
-                        <property name="visible">True</property>
-                        <property name="sensitive">False</property>
-                        <property name="can_focus">True</property>
-                        <property name="can_default">True</property>
-                        <property name="label">gtk-delete</property>
-                        <property name="use_stock">True</property>
-                        <property name="response_id">0</property>
-                      </widget>
-                      <packing>
-                        <property name="position">2</property>
-                      </packing>
+                      <placeholder/>
                     </child>
                   </widget>
                   <packing>

Modified: trunk/src/connection-editor/nm-connection-editor.h
==============================================================================
--- trunk/src/connection-editor/nm-connection-editor.h	(original)
+++ trunk/src/connection-editor/nm-connection-editor.h	Fri Apr  3 13:28:12 2009
@@ -67,7 +67,8 @@
 
 GType               nm_connection_editor_get_type (void);
 NMConnectionEditor *nm_connection_editor_new (NMConnection *connection,
-                                              gboolean system_settings_can_modify);
+                                              gboolean system_settings_can_modify,
+                                              GError **error);
 
 void                nm_connection_editor_present (NMConnectionEditor *editor);
 void                nm_connection_editor_run (NMConnectionEditor *editor);

Modified: trunk/src/connection-editor/nm-connection-list.c
==============================================================================
--- trunk/src/connection-editor/nm-connection-list.c	(original)
+++ trunk/src/connection-editor/nm-connection-list.c	Fri Apr  3 13:28:12 2009
@@ -57,6 +57,7 @@
 #include "mobile-wizard.h"
 #include "utils.h"
 #include "vpn-helpers.h"
+#include "polkit-helpers.h"
 
 G_DEFINE_TYPE (NMConnectionList, nm_connection_list, G_TYPE_OBJECT)
 
@@ -75,30 +76,34 @@
 typedef struct {
 	NMConnectionList *list;
 	GtkTreeView *treeview;
+	GtkWindow *list_window;
 	GtkWidget *button;
+	PolKitAction *action;
+	PolKitGnomeAction *gnome_action;
 } ActionInfo;
 
 static void
-show_error_dialog (GtkWindow *parent, const gchar *format, ...)
+error_dialog (GtkWindow *parent, const char *heading, const char *format, ...)
 {
 	GtkWidget *dialog;
 	va_list args;
-	char *msg;
+	char *message;
+
+	dialog = gtk_message_dialog_new (parent,
+	                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+	                                 GTK_MESSAGE_ERROR,
+	                                 GTK_BUTTONS_CLOSE,
+	                                 "%s", heading);
 
 	va_start (args, format);
-	msg = g_strdup_vprintf (format, args);
+	message = g_strdup_vprintf (format, args);
 	va_end (args);
 
-	dialog = gtk_message_dialog_new (NULL,
-							   GTK_DIALOG_DESTROY_WITH_PARENT,
-							   GTK_MESSAGE_ERROR,
-							   GTK_BUTTONS_CLOSE,
-							   "%s", msg);
-	g_free (msg);
-
-	if (parent)
-		gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), message);
+	g_free (message);
 
+	gtk_widget_show_all (dialog);
+	gtk_window_present (GTK_WINDOW (dialog));
 	gtk_dialog_run (GTK_DIALOG (dialog));
 	gtk_widget_destroy (dialog);
 }
@@ -280,50 +285,6 @@
 
 
 /**********************************************/
-/* PolKit helpers */
-
-static gboolean
-is_permission_denied_error (GError *error)
-{
-	return dbus_g_error_has_name (error, "org.freedesktop.NetworkManagerSettings.Connection.NotPrivileged") ||
-		dbus_g_error_has_name (error, "org.freedesktop.NetworkManagerSettings.System.NotPrivileged");
-}
-
-static gboolean
-obtain_auth (GError *pk_error,
-             GtkWindow *parent,
-             PolKitGnomeAuthCB callback,
-             gpointer user_data,
-             GError **error)
-{
-	PolKitAction *pk_action;
-	char **tokens;
-	gboolean success = FALSE;
-	guint xid = 0;
-
-	tokens = g_strsplit (pk_error->message, " ", 2);
-	if (g_strv_length (tokens) != 2) {
-		g_set_error (error, 0, 0, "%s", _("PolicyKit authorization was malformed."));
-		goto out;
-	}
-
-	pk_action = polkit_action_new_from_string_representation (tokens[0]);
-	if (!pk_action) {
-		g_set_error (error, 0, 0, "%s", _("PolicyKit authorization could not be created."));
-		goto out;
-	}
-
-	if (parent)
-		xid = gdk_x11_drawable_get_xid (GDK_DRAWABLE (GTK_WIDGET (parent)->window));
-	success = polkit_gnome_auth_obtain (pk_action, xid, getpid (), callback, user_data, error);
-	polkit_action_unref (pk_action);
-
-out:
-	g_strfreev (tokens);
-	return success;
-}
-
-/**********************************************/
 /* Connection removing */
 
 typedef void (*ConnectionRemovedFn) (NMExportedConnection *exported,
@@ -355,10 +316,15 @@
 		remove_connection (info->exported, info->parent, info->callback, info->user_data);
 		done = FALSE;
 	} else if (error) {
-		show_error_dialog (info->parent, _("Could not obtain required privileges: %s."), error->message);
+		error_dialog (info->parent,
+		              _("Could not obtain required privileges"),
+		              "%s", error->message);
 		g_error_free (error);
-	} else
-		show_error_dialog (info->parent, _("Could not remove system connection: permission denied."));
+	} else {
+		error_dialog (info->parent,
+		              _("Could not delete connection"),
+		              "%s", _("The connection could not be deleted due to an unknown error."));
+	}
 
 	if (done && info->callback)
 		info->callback (info->exported, FALSE, info->user_data);
@@ -380,7 +346,7 @@
 	if (!success) {
 		gboolean auth_pending = FALSE;
 
-		if (is_permission_denied_error (error)) {
+		if (pk_helper_is_permission_denied_error (error)) {
 			ConnectionRemoveInfo *info;
 			GError *auth_error = NULL;
 
@@ -390,11 +356,11 @@
 			info->callback = callback;
 			info->user_data = user_data;
 
-			auth_pending = obtain_auth (error, parent, remove_connection_cb, info, &auth_error);
+			auth_pending = pk_helper_obtain_auth (error, parent, remove_connection_cb, info, &auth_error);
 			if (auth_error) {
-				show_error_dialog (parent,
-				                   _("Removing connection failed: %s."),
-				                   auth_error->message);
+				error_dialog (parent,
+				              _("Could not move connection"),
+				              "%s", auth_error->message);
 				g_error_free (auth_error);
 			}
 
@@ -402,8 +368,11 @@
 				g_object_unref (info->exported);
 				g_slice_free (ConnectionRemoveInfo, info);
 			}
-		} else
-			show_error_dialog (parent, _("Removing connection failed: %s."), error->message);
+		} else {
+			error_dialog (parent,
+			              _("Could not move connection"),
+			              "%s", error->message);
+		}
 
 		g_error_free (error);
 
@@ -479,10 +448,15 @@
 		add_connection (info->list, info->editor, info->connection, info->callback, info->user_data);
 		done = FALSE;
 	} else if (error) {
-		show_error_dialog (parent, _("Could not obtain required privileges: %s."), error->message);
+		error_dialog (parent,
+		              _("Could not obtain required privileges"),
+		              "%s", error->message);
 		g_error_free (error);
-	} else
-		show_error_dialog (parent, _("Could not add system connection: permission denied."));
+	} else {
+		error_dialog (parent,
+		              _("Could not add connection"),
+		              "%s", _("The connection could not be added due to an unknown error."));
+	}
 
 	if (done && info->callback)
 		info->callback (NULL, FALSE, info->user_data);
@@ -515,7 +489,7 @@
 			GtkWindow *parent;
 
 			parent = nm_connection_editor_get_window (editor);
-			if (is_permission_denied_error (error)) {
+			if (pk_helper_is_permission_denied_error (error)) {
 				ConnectionAddInfo *info;
 				GError *auth_error = NULL;
 
@@ -526,11 +500,11 @@
 				info->callback = callback;
 				info->user_data = user_data;
 
-				pending_auth = obtain_auth (error, parent, add_connection_cb, info, &auth_error);
+				pending_auth = pk_helper_obtain_auth (error, parent, add_connection_cb, info, &auth_error);
 				if (auth_error) {
-					show_error_dialog (parent,
-					                   _("Adding connection failed: %s."),
-					                   auth_error->message);
+					error_dialog (parent,
+					              _("Could not add connection"),
+					              "%s", auth_error->message);
 					g_error_free (auth_error);
 				}
 
@@ -538,8 +512,11 @@
 					g_object_unref (info->connection);
 					g_slice_free (ConnectionAddInfo, info);
 				}
-			} else
-				show_error_dialog (parent, _("Adding connection failed: %s."), error->message);
+			} else {
+				error_dialog (parent,
+				              _("Could not add connection"),
+				              "%s", error->message);
+			}
 
 			g_error_free (error);
 
@@ -650,10 +627,15 @@
 		update_connection (info->list, info->editor, info->original, info->modified, info->callback, info->user_data);
 		done = FALSE;
 	} else if (error) {
-		show_error_dialog (parent, _("Could not obtain required privileges: %s."), error->message);
+		error_dialog (parent,
+		              _("Could not update connection"),
+		              "%s", error->message);
 		g_error_free (error);
-	} else
-		show_error_dialog (parent, _("Could not update system connection: permission denied."));
+	} else {
+		error_dialog (parent,
+		              _("Could not update connection"),
+		              "%s", _("The connection could not be updated due to an unknown error."));
+	}
 
 	if (done)
 		connection_update_done (info, FALSE);
@@ -705,18 +687,21 @@
 
 		parent = nm_connection_editor_get_window (editor);
 		if (!success) {
-			if (is_permission_denied_error (error)) {
+			if (pk_helper_is_permission_denied_error (error)) {
 				GError *auth_error = NULL;
 
-				pending_auth = obtain_auth (error, parent, update_connection_cb, info, &auth_error);
+				pending_auth = pk_helper_obtain_auth (error, parent, update_connection_cb, info, &auth_error);
 				if (auth_error) {
-					show_error_dialog (parent,
-					                   _("Updating connection failed: %s."),
-					                   auth_error->message);
+					error_dialog (parent,
+					              _("Could not update connection"),
+					              "%s", auth_error->message);
 					g_error_free (auth_error);
 				}
-			} else
-				show_error_dialog (parent, _("Updating connection failed: %s."), error->message);
+			} else {
+				error_dialog (parent,
+				              _("Could not update connection"),
+				              "%s", error->message);
+			}
 
 			g_error_free (error);
 		} else {
@@ -736,14 +721,29 @@
 }
 
 static void
-add_done_cb (NMConnectionEditor *editor, gint response, gpointer user_data)
+add_done_cb (NMConnectionEditor *editor, gint response, GError *error, gpointer user_data)
 {
 	ActionInfo *info = (ActionInfo *) user_data;
 	NMConnection *connection;
+	const char *message = _("An unknown error ocurred.");
 
 	connection = nm_connection_editor_get_connection (editor);
-	if (response == GTK_RESPONSE_OK)
+
+	switch (response) {
+	case GTK_RESPONSE_NONE:
+		if (error && error->message)
+			message = error->message;
+		error_dialog (GTK_WINDOW (editor->window),
+		              _("Error initializing editor"),
+		              "%s", message);
+		break;
+	case GTK_RESPONSE_OK:
 		add_connection (info->list, editor, connection, NULL, NULL);
+		break;
+	default:
+		g_assert_not_reached ();
+		break;
+	}
 
 	g_hash_table_remove (info->list->editors, connection);
 }
@@ -992,6 +992,8 @@
 	const char *connection_type;
 	NMConnection *connection;
 	NMConnectionEditor *editor;
+	GError *error = NULL;
+	const char *message = _("The connection editor dialog could not be initialized due to an unknown error.");
 
 	connection_type = get_connection_type_from_treeview (info->list, info->treeview);
 	g_assert (connection_type);
@@ -1003,7 +1005,16 @@
 	}
 
 	editor = nm_connection_editor_new (connection,
-	                                   nm_dbus_settings_system_get_can_modify (info->list->system_settings));
+	                                   nm_dbus_settings_system_get_can_modify (info->list->system_settings),
+	                                   &error);
+	if (!editor) {
+		error_dialog (info->list_window,
+		              _("Could not edit new connection"),
+		              "%s",
+		              (error && error->message) ? error->message : message);
+		return;
+	}
+
 	g_signal_connect (G_OBJECT (editor), "done", G_CALLBACK (add_done_cb), info);
 	g_hash_table_insert (info->list->editors, connection, editor);
 
@@ -1037,21 +1048,26 @@
 }
 
 static void
-edit_done_cb (NMConnectionEditor *editor, gint response, gpointer user_data)
+edit_done_cb (NMConnectionEditor *editor, gint response, GError *error, gpointer user_data)
 {
 	EditConnectionInfo *info = (EditConnectionInfo *) user_data;
+	const char *message = _("An unknown error ocurred.");
 
 	g_hash_table_remove (info->list->editors, info->original_connection);
 
-	if (response == GTK_RESPONSE_OK) {
+	if (response == GTK_RESPONSE_NONE) {
+		if (error && error->message)
+			message = error->message;
+		error_dialog (GTK_WINDOW (editor->window), _("Error initializing editor"), "%s", message);
+	} else if (response == GTK_RESPONSE_OK) {
 		NMConnection *connection;
-		GError *error = NULL;
+		GError *edit_error = NULL;
 		gboolean success;
 
 		connection = nm_connection_editor_get_connection (editor);
 
 		utils_fill_connection_certs (connection);
-		success = nm_connection_verify (connection, &error);
+		success = nm_connection_verify (connection, &edit_error);
 		utils_clear_filled_connection_certs (connection);
 
 		if (success) {
@@ -1061,9 +1077,9 @@
 			g_warning ("%s: invalid connection after update: bug in the "
 			           "'%s' / '%s' invalid: %d",
 			           __func__,
-			           g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)),
-			           error->message, error->code);
-			g_error_free (error);
+			           g_type_name (nm_connection_lookup_setting_type_by_quark (edit_error->domain)),
+			           edit_error->message, edit_error->code);
+			g_error_free (edit_error);
 			connection_updated_cb (info->list, FALSE, user_data);
 		}
 	}
@@ -1076,6 +1092,8 @@
 	NMConnection *connection;
 	NMConnectionEditor *editor;
 	EditConnectionInfo *edit_info;
+	GError *error = NULL;
+	const char *message = _("The connection editor dialog could not be initialized due to an unknown error.");
 
 	exported = get_active_connection (info->treeview);
 	g_return_if_fail (exported != NULL);
@@ -1089,9 +1107,18 @@
 
 	connection = nm_gconf_connection_duplicate (nm_exported_connection_get_connection (exported));
 	editor = nm_connection_editor_new (connection,
-	                                   nm_dbus_settings_system_get_can_modify (info->list->system_settings));
+	                                   nm_dbus_settings_system_get_can_modify (info->list->system_settings),
+	                                   &error);
 	g_object_unref (connection);
 
+	if (!editor) {
+		error_dialog (info->list_window,
+		              _("Could not edit connection"),
+		              "%s",
+		              (error && error->message) ? error->message : message);
+		return;
+	}
+
 	edit_info = g_new (EditConnectionInfo, 1);
 	edit_info->list = info->list;
 	edit_info->original_connection = g_object_ref (exported);
@@ -1160,21 +1187,41 @@
 		remove_connection (exported, GTK_WINDOW (info->list->dialog), connection_remove_done, info->list);
 }
 
-static void
-list_selection_changed_cb (GtkTreeSelection *selection, gpointer user_data)
+static gboolean
+check_sensitivity (ActionInfo *info, PolKitResult pk_result)
 {
-	ActionInfo *info = (ActionInfo *) user_data;
-	GtkTreeIter iter;
-	GtkTreeModel *model;
+	gboolean sensitive = TRUE;
+	NMExportedConnection *exported = NULL;
+	NMConnection *connection = NULL;
+
+	exported = get_active_connection (info->treeview);
+	if (exported)
+		connection = nm_exported_connection_get_connection (exported);
+	if (!connection)
+		return FALSE;
 
-	if (gtk_tree_selection_get_selected (selection, &model, &iter))
-		gtk_widget_set_sensitive (info->button, TRUE);
-	else
-		gtk_widget_set_sensitive (info->button, FALSE);
+	if (nm_connection_get_scope (connection) != NM_CONNECTION_SCOPE_SYSTEM)
+		return TRUE;
+
+	if (pk_result == POLKIT_RESULT_UNKNOWN)
+		pk_result = polkit_gnome_action_get_polkit_result (info->gnome_action);
+
+	if (pk_result == POLKIT_RESULT_NO || pk_result == POLKIT_RESULT_UNKNOWN)
+		sensitive = FALSE;
+
+	return sensitive;
+}
+
+static void
+system_pk_result_changed_cb (PolKitGnomeAction *gnome_action,
+                             PolKitResult result,
+                             ActionInfo *info)
+{
+	gtk_widget_set_sensitive (info->button, check_sensitivity (info, result));
 }
 
 static void
-delete_selection_changed_cb (GtkTreeSelection *selection, gpointer user_data)
+pk_button_selection_changed_cb (GtkTreeSelection *selection, gpointer user_data)
 {
 	ActionInfo *info = (ActionInfo *) user_data;
 	GtkTreeIter iter;
@@ -1182,7 +1229,8 @@
 	NMExportedConnection *exported;
 	NMConnection *connection = NULL;
 	NMSettingConnection *s_con;
-	gboolean can_delete = TRUE;
+	gboolean can_do_action = FALSE;
+	gboolean req_privs = FALSE;
 
 	if (!gtk_tree_selection_get_selected (selection, &model, &iter))
 		goto done;
@@ -1196,13 +1244,17 @@
 	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
 	g_assert (s_con);
 
-	if (nm_setting_connection_get_read_only (s_con)) {
-		can_delete = FALSE;
-		goto done;
+	if (nm_connection_get_scope (connection) != NM_CONNECTION_SCOPE_SYSTEM)
+		can_do_action = !nm_setting_connection_get_read_only (s_con);
+	else {
+		if (!nm_setting_connection_get_read_only (s_con))
+			can_do_action = check_sensitivity (info, POLKIT_RESULT_UNKNOWN);
+		req_privs = TRUE;
 	}
 
 done:
-	gtk_widget_set_sensitive (info->button, can_delete);
+	g_object_set (info->gnome_action, "polkit-action", req_privs ? info->action : NULL, NULL);
+	g_object_set (info->gnome_action, "master-sensitive", can_do_action, NULL);
 }
 
 static void
@@ -1255,6 +1307,8 @@
 	NMSettingVPN *s_vpn;
 	const char *service_type;
 	char *s;
+	GError *error = NULL;
+	const char *message = _("The connection editor dialog could not be initialized due to an unknown error.");
 
 	/* Basic sanity checks of the connection */
 	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
@@ -1294,6 +1348,7 @@
 		                                 _("Cannot import VPN connection"));
 		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
 		                                 _("The VPN plugin failed to import the VPN connection correctly\n\nError: no VPN service type."));
+		gtk_window_set_transient_for (GTK_WINDOW (dialog), info->list_window);
 		g_signal_connect (dialog, "delete-event", G_CALLBACK (gtk_widget_destroy), NULL);
 		g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
 		gtk_widget_show_all (dialog);
@@ -1302,7 +1357,16 @@
 	}
 
 	editor = nm_connection_editor_new (connection,
-	                                   nm_dbus_settings_system_get_can_modify (info->list->system_settings));
+	                                   nm_dbus_settings_system_get_can_modify (info->list->system_settings),
+	                                   &error);
+	if (!editor) {
+		error_dialog (info->list_window,
+		              _("Could not edit imported connection"),
+		              "%s",
+		              (error && error->message) ? error->message : message);
+		return;
+	}
+
 	g_signal_connect (G_OBJECT (editor), "done", G_CALLBACK (add_done_cb), info);
 	g_hash_table_insert (info->list->editors, connection, editor);
 
@@ -1337,7 +1401,10 @@
                               GtkTreeViewColumn *column,
                               gpointer user_data)
 {
-	do_edit ((ActionInfo *) user_data);
+	ActionInfo *info = user_data;
+
+	if (GTK_WIDGET_SENSITIVE (info->button))
+		do_edit ((ActionInfo *) user_data);
 }
 
 static void
@@ -1350,6 +1417,9 @@
 nm_connection_list_init (NMConnectionList *list)
 {
 	list->treeviews = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+	list->system_action = polkit_action_new ();
+	polkit_action_set_action_id (list->system_action, "org.freedesktop.network-manager-settings.system.modify");
 }
 
 static void
@@ -1374,6 +1444,8 @@
 	if (list->unknown_icon)
 		g_object_unref (list->unknown_icon);
 
+	polkit_action_unref (list->system_action);
+
 	if (list->dialog)
 		gtk_widget_destroy (list->dialog);
 	if (list->gui)
@@ -1458,21 +1530,50 @@
 	return treeview;
 }
 
+static void
+action_info_free (ActionInfo *info)
+{
+	g_return_if_fail (info != NULL);
+
+	/* gnome_action should have been destroyed when the dialog got destroyed */
+	polkit_action_unref (info->action);
+	g_free (info);
+}
+
 static ActionInfo *
-new_action_info (NMConnectionList *list, GtkTreeView *treeview, GtkWidget *button)
+action_info_new (NMConnectionList *list,
+                 GtkTreeView *treeview,
+                 GtkWindow *list_window,
+                 GtkWidget *button,
+                 PolKitAction *action)
 {
 	ActionInfo *info;
 
 	info = g_malloc0 (sizeof (ActionInfo));
-	g_object_weak_ref (G_OBJECT (list), (GWeakNotify) g_free, info);
+	g_object_weak_ref (G_OBJECT (list), (GWeakNotify) action_info_free, info);
 
 	info->list = list;
 	info->treeview = treeview;
+	info->list_window = list_window;
 	info->button = button;
+	info->action = polkit_action_ref (action);
 	return info;
 }
 
 static void
+action_info_set_button (ActionInfo *info,
+                        GtkWidget *button,
+                        PolKitGnomeAction *gnome_action)
+{
+	g_return_if_fail (info != NULL);
+
+	info->button = button;
+	if (info->gnome_action)
+		g_object_unref (info->gnome_action);
+	info->gnome_action = gnome_action;
+}
+
+static void
 check_vpn_import_supported (gpointer key, gpointer data, gpointer user_data)
 {
 	NMVpnPluginUiInterface *plugin = NM_VPN_PLUGIN_UI_INTERFACE (data);
@@ -1485,6 +1586,68 @@
 		*import_supported = TRUE;
 }
 
+static GtkWidget *
+create_system_action_button (const char *name,
+                             const char *auth_label,
+                             const char *auth_tooltip,
+                             const char *label,
+                             const char *tooltip,
+                             const char *stock_icon,
+                             const char *auth_icon,
+                             GCallback result_callback,
+                             GtkWidget *hbox,
+                             PolKitGnomeAction **out_action,
+                             gpointer user_data)
+{
+	PolKitGnomeAction *action;
+	GtkWidget *button;
+
+	action = polkit_gnome_action_new (name);
+
+	g_object_set (action,
+	              "polkit-action", NULL,
+
+	              "self-blocked-visible",       TRUE,
+	              "self-blocked-sensitive",     FALSE,
+	              "self-blocked-short-label",   label,
+	              "self-blocked-label",         label,
+	              "self-blocked-tooltip",       tooltip,
+	              "self-blocked-icon-name",     stock_icon,
+
+	              "no-visible",       TRUE,
+	              "no-sensitive",     FALSE,
+	              "no-short-label",   label,
+	              "no-label",         label,
+	              "no-tooltip",       tooltip,
+	              "no-icon-name",     stock_icon,
+
+	              "auth-visible",     TRUE,
+	              "auth-sensitive",   TRUE,
+	              "auth-short-label", auth_label,
+	              "auth-label",       auth_label,
+	              "auth-tooltip",     auth_tooltip,
+	              "auth-icon-name",   auth_icon,
+
+	              "yes-visible",      TRUE,
+	              "yes-sensitive",    TRUE,
+	              "yes-short-label",  label,
+	              "yes-label",        label,
+	              "yes-tooltip",      tooltip,
+	              "yes-icon-name",    stock_icon,
+
+	              "master-visible",   TRUE,
+	              "master-sensitive", TRUE,
+	              NULL);
+	g_signal_connect (action, "polkit-result-changed",
+	                  G_CALLBACK (result_callback), user_data);
+
+	button = polkit_gnome_action_create_button (action);
+	gtk_box_pack_end (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+
+	*out_action = action;
+	return button;
+}
+
 static void
 add_connection_buttons (NMConnectionList *self,
                         const char *prefix,
@@ -1492,9 +1655,10 @@
                         gboolean is_vpn)
 {
 	char *name;
-	GtkWidget *button;
+	GtkWidget *button, *hbox;
 	ActionInfo *info;
 	GtkTreeSelection *selection;
+	PolKitGnomeAction *action = NULL;
 
 	selection = gtk_tree_view_get_selection (treeview);
 
@@ -1502,7 +1666,7 @@
 	name = g_strdup_printf ("%s_add", prefix);
 	button = glade_xml_get_widget (self->gui, name);
 	g_free (name);
-	info = new_action_info (self, treeview, NULL);
+	info = action_info_new (self, treeview, GTK_WINDOW (self->dialog), NULL, self->system_action);
 	g_signal_connect (button, "clicked", G_CALLBACK (add_connection_clicked), info);
 	if (is_vpn) {
 		GHashTable *plugins;
@@ -1512,22 +1676,48 @@
 		gtk_widget_set_sensitive (button, (plugins && g_hash_table_size (plugins)));
 	}
 
-	/* Edit */
-	name = g_strdup_printf ("%s_edit", prefix);
-	button = glade_xml_get_widget (self->gui, name);
+	name = g_strdup_printf ("%s_button_box", prefix);
+	hbox = glade_xml_get_widget (self->gui, name);
 	g_free (name);
-	info = new_action_info (self, treeview, button);
+
+	/* Edit */
+	info = action_info_new (self, treeview, GTK_WINDOW (self->dialog), NULL, self->system_action);
+	action = NULL;
+	button = create_system_action_button ("system-edit",
+	                                      _("Edit..."),
+	                                      _("Authenticate to edit the selected connection."),
+	                                      _("Edit"),
+	                                      _("Edit the selected connection."),
+	                                      GTK_STOCK_EDIT,
+	                                      GTK_STOCK_DIALOG_AUTHENTICATION,
+	                                      G_CALLBACK (system_pk_result_changed_cb),
+	                                      hbox,
+	                                      &action,
+	                                      info);
+	action_info_set_button (info, button, action);
 	g_signal_connect (button, "clicked", G_CALLBACK (edit_connection_cb), info);
-	g_signal_connect (selection, "changed", G_CALLBACK (list_selection_changed_cb), info);
 	g_signal_connect (treeview, "row-activated", G_CALLBACK (connection_double_clicked_cb), info);
+	g_signal_connect (selection, "changed", G_CALLBACK (pk_button_selection_changed_cb), info);
+	pk_button_selection_changed_cb (selection, info);
 
 	/* Delete */
-	name = g_strdup_printf ("%s_delete", prefix);
-	button = glade_xml_get_widget (self->gui, name);
-	g_free (name);
-	info = new_action_info (self, treeview, button);
+	info = action_info_new (self, treeview, GTK_WINDOW (self->dialog), NULL, self->system_action);
+	action = NULL;
+	button = create_system_action_button ("system-delete",
+	                                      _("Delete..."),
+	                                      _("Authenticate to delete the selected connection."),
+	                                      _("Delete"),
+	                                      _("Delete the selected connection."),
+	                                      GTK_STOCK_DELETE,
+	                                      GTK_STOCK_DIALOG_AUTHENTICATION,
+	                                      G_CALLBACK (system_pk_result_changed_cb),
+	                                      hbox,
+	                                      &action,
+	                                      info);
+	action_info_set_button (info, button, action);
 	g_signal_connect (button, "clicked", G_CALLBACK (delete_connection_cb), info);
-	g_signal_connect (selection, "changed", G_CALLBACK (delete_selection_changed_cb), info);
+	g_signal_connect (selection, "changed", G_CALLBACK (pk_button_selection_changed_cb), info);
+	pk_button_selection_changed_cb (selection, info);
 
 	/* Import */
 	name = g_strdup_printf ("%s_import", prefix);
@@ -1536,7 +1726,7 @@
 	if (button) {
 		gboolean import_supported = FALSE;
 
-		info = new_action_info (self, treeview, button);
+		info = action_info_new (self, treeview, GTK_WINDOW (self->dialog), button, self->system_action);
 		g_signal_connect (button, "clicked", G_CALLBACK (import_vpn_cb), info);
 
 		g_hash_table_foreach (vpn_get_plugins (NULL), check_vpn_import_supported, &import_supported);
@@ -1548,7 +1738,7 @@
 	button = glade_xml_get_widget (self->gui, name);
 	g_free (name);
 	if (button) {
-		info = new_action_info (self, treeview, button);
+		info = action_info_new (self, treeview, GTK_WINDOW (self->dialog), button, self->system_action);
 		g_signal_connect (button, "clicked", G_CALLBACK (export_vpn_cb), info);
 		g_signal_connect (selection, "changed", G_CALLBACK (vpn_list_selection_changed_cb), info);
 		gtk_widget_set_sensitive (button, FALSE);

Modified: trunk/src/connection-editor/nm-connection-list.h
==============================================================================
--- trunk/src/connection-editor/nm-connection-list.h	(original)
+++ trunk/src/connection-editor/nm-connection-list.h	Fri Apr  3 13:28:12 2009
@@ -29,6 +29,11 @@
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
 #include <nm-dbus-settings-system.h>
+#ifdef NO_POLKIT_GNOME
+#include "polkit-gnome.h"
+#else
+#include <polkit-gnome/polkit-gnome.h>
+#endif
 #include "nma-gconf-settings.h"
 
 #define NM_TYPE_CONNECTION_LIST    (nm_connection_list_get_type ())
@@ -49,6 +54,8 @@
 	GladeXML *gui;
 	GtkWidget *dialog;
 
+	PolKitAction *system_action;
+
 	GdkPixbuf *wired_icon;
 	GdkPixbuf *wireless_icon;
 	GdkPixbuf *wwan_icon;

Modified: trunk/src/connection-editor/page-dsl.c
==============================================================================
--- trunk/src/connection-editor/page-dsl.c	(original)
+++ trunk/src/connection-editor/page-dsl.c	Fri Apr  3 13:28:12 2009
@@ -115,26 +115,48 @@
 	gtk_entry_set_visibility (priv->password, gtk_toggle_button_get_active (button));
 }
 
-CEPageDsl *
-ce_page_dsl_new (NMConnection *connection)
+static void
+finish_setup (CEPageDsl *self, gpointer unused, GError *error, gpointer user_data)
+{
+	CEPage *parent = CE_PAGE (self);
+	CEPageDslPrivate *priv = CE_PAGE_DSL_GET_PRIVATE (self);
+
+	if (error)
+		return;
+
+	populate_ui (self, parent->connection);
+
+	g_signal_connect (priv->username, "changed", G_CALLBACK (stuff_changed), self);
+	g_signal_connect (priv->password, "changed", G_CALLBACK (stuff_changed), self);
+	g_signal_connect (priv->service, "changed", G_CALLBACK (stuff_changed), self);
+
+	g_signal_connect (glade_xml_get_widget (parent->xml, "dsl_show_password"), "toggled",
+					  G_CALLBACK (show_password), self);
+}
+
+CEPage *
+ce_page_dsl_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
 {
 	CEPageDsl *self;
 	CEPageDslPrivate *priv;
 	CEPage *parent;
 
-	self = CE_PAGE_DSL (g_object_new (CE_TYPE_PAGE_DSL, NULL));
+	self = CE_PAGE_DSL (g_object_new (CE_TYPE_PAGE_DSL,
+	                                  CE_PAGE_CONNECTION, connection,
+	                                  CE_PAGE_PARENT_WINDOW, parent_window,
+	                                  NULL));
 	parent = CE_PAGE (self);
 
 	parent->xml = glade_xml_new (GLADEDIR "/ce-page-dsl.glade", "DslPage", NULL);
 	if (!parent->xml) {
-		g_warning ("%s: Couldn't load dsl page glade file.", __func__);
+		g_set_error (error, 0, 0, "%s", _("Could not load DSL user interface."));
 		g_object_unref (self);
 		return NULL;
 	}
 
 	parent->page = glade_xml_get_widget (parent->xml, "DslPage");
 	if (!parent->page) {
-		g_warning ("%s: Couldn't load dsl page from glade file.", __func__);
+		g_set_error (error, 0, 0, "%s", _("Could not load DSL user interface."));
 		g_object_unref (self);
 		return NULL;
 	}
@@ -151,16 +173,13 @@
 		nm_connection_add_setting (connection, NM_SETTING (priv->setting));
 	}
 
-	populate_ui (self, connection);
-
-	g_signal_connect (priv->username, "changed", G_CALLBACK (stuff_changed), self);
-	g_signal_connect (priv->password, "changed", G_CALLBACK (stuff_changed), self);
-	g_signal_connect (priv->service, "changed", G_CALLBACK (stuff_changed), self);
-
-	g_signal_connect (glade_xml_get_widget (parent->xml, "dsl_show_password"), "toggled",
-					  G_CALLBACK (show_password), self);
+	g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
+	if (!ce_page_initialize (parent, NM_SETTING_PPPOE_SETTING_NAME, error)) {
+		g_object_unref (self);
+		return NULL;
+	}
 
-	return self;
+	return CE_PAGE (self);
 }
 
 static void

Modified: trunk/src/connection-editor/page-dsl.h
==============================================================================
--- trunk/src/connection-editor/page-dsl.h	(original)
+++ trunk/src/connection-editor/page-dsl.h	Fri Apr  3 13:28:12 2009
@@ -47,6 +47,6 @@
 
 GType ce_page_dsl_get_type (void);
 
-CEPageDsl *ce_page_dsl_new (NMConnection *connection);
+CEPage *ce_page_dsl_new (NMConnection *connection, GtkWindow *parent, GError **error);
 
 #endif  /* __PAGE_DSL_H__ */

Modified: trunk/src/connection-editor/page-ip4.c
==============================================================================
--- trunk/src/connection-editor/page-ip4.c	(original)
+++ trunk/src/connection-editor/page-ip4.c	Fri Apr  3 13:28:12 2009
@@ -604,53 +604,18 @@
 	gtk_widget_show_all (dialog);
 }
 
-CEPageIP4 *
-ce_page_ip4_new (NMConnection *connection)
+static void
+finish_setup (CEPageIP4 *self, gpointer unused, GError *error, gpointer user_data)
 {
-	CEPageIP4 *self;
-	CEPageIP4Private *priv;
-	CEPage *parent;
-	NMSettingConnection *s_con;
+	CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self);
 	GtkTreeSelection *selection;
 	gint offset;
 	GtkTreeViewColumn *column;
 	GtkCellRenderer *renderer;
 	GtkListStore *store;
 
-	self = CE_PAGE_IP4 (g_object_new (CE_TYPE_PAGE_IP4, NULL));
-	parent = CE_PAGE (self);
-
-	parent->xml = glade_xml_new (GLADEDIR "/ce-page-ip4.glade", "IP4Page", NULL);
-	if (!parent->xml) {
-		g_warning ("%s: Couldn't load wired page glade file.", __func__);
-		g_object_unref (self);
-		return NULL;
-	}
-
-	parent->page = glade_xml_get_widget (parent->xml, "IP4Page");
-	if (!parent->page) {
-		g_warning ("%s: Couldn't load wired page from glade file.", __func__);
-		g_object_unref (self);
-		return NULL;
-	}
-	g_object_ref_sink (parent->page);
-
-	parent->title = g_strdup (_("IPv4 Settings"));
-
-	ip4_private_init (self, connection);
-	priv = CE_PAGE_IP4_GET_PRIVATE (self);
-
-	priv->window_group = gtk_window_group_new ();
-
-	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
-	g_assert (s_con);
-	priv->connection_id = g_strdup (nm_setting_connection_get_id (s_con));
-
-	priv->setting = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
-	if (!priv->setting) {
-		priv->setting = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
-		nm_connection_add_setting (connection, NM_SETTING (priv->setting));
-	}
+	if (error)
+		return;
 
 	populate_ui (self);
 
@@ -722,8 +687,61 @@
 	g_signal_connect_swapped (priv->dhcp_client_id, "changed", G_CALLBACK (ce_page_changed), self);
 
 	g_signal_connect (priv->routes_button, "clicked", G_CALLBACK (routes_button_clicked_cb), self);
+}
+
+CEPage *
+ce_page_ip4_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
+{
+	CEPageIP4 *self;
+	CEPageIP4Private *priv;
+	CEPage *parent;
+	NMSettingConnection *s_con;
+
+	self = CE_PAGE_IP4 (g_object_new (CE_TYPE_PAGE_IP4,
+	                                  CE_PAGE_CONNECTION, connection,
+	                                  CE_PAGE_PARENT_WINDOW, parent_window,
+	                                  NULL));
+	parent = CE_PAGE (self);
+
+	parent->xml = glade_xml_new (GLADEDIR "/ce-page-ip4.glade", "IP4Page", NULL);
+	if (!parent->xml) {
+		g_set_error (error, 0, 0, "%s", _("Could not load IPv4 user interface."));
+		g_object_unref (self);
+		return NULL;
+	}
+
+	parent->page = glade_xml_get_widget (parent->xml, "IP4Page");
+	if (!parent->page) {
+		g_set_error (error, 0, 0, "%s", _("Could not load IPv4 user interface."));
+		g_object_unref (self);
+		return NULL;
+	}
+	g_object_ref_sink (parent->page);
+
+	parent->title = g_strdup (_("IPv4 Settings"));
+
+	ip4_private_init (self, connection);
+	priv = CE_PAGE_IP4_GET_PRIVATE (self);
+
+	priv->window_group = gtk_window_group_new ();
+
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+	g_assert (s_con);
+	priv->connection_id = g_strdup (nm_setting_connection_get_id (s_con));
+
+	priv->setting = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
+	if (!priv->setting) {
+		priv->setting = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
+		nm_connection_add_setting (connection, NM_SETTING (priv->setting));
+	}
+
+	g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
+	if (!ce_page_initialize (parent, NULL, error)) {
+		g_object_unref (self);
+		return NULL;
+	}
 
-	return self;
+	return CE_PAGE (self);
 }
 
 static void

Modified: trunk/src/connection-editor/page-ip4.h
==============================================================================
--- trunk/src/connection-editor/page-ip4.h	(original)
+++ trunk/src/connection-editor/page-ip4.h	Fri Apr  3 13:28:12 2009
@@ -47,7 +47,7 @@
 
 GType ce_page_ip4_get_type (void);
 
-CEPageIP4 *ce_page_ip4_new (NMConnection *connection);
+CEPage *ce_page_ip4_new (NMConnection *connection, GtkWindow *parent, GError **error);
 
 #endif  /* __PAGE_IP4_H__ */
 

Modified: trunk/src/connection-editor/page-mobile.c
==============================================================================
--- trunk/src/connection-editor/page-mobile.c	(original)
+++ trunk/src/connection-editor/page-mobile.c	Fri Apr  3 13:28:12 2009
@@ -227,19 +227,6 @@
 }
 
 static void
-populate_ui (CEPageMobile *self, NMConnection *connection)
-{
-	CEPageMobilePrivate *priv = CE_PAGE_MOBILE_GET_PRIVATE (self);
-
-	if (NM_IS_SETTING_GSM (priv->setting))
-		populate_gsm_ui (self, connection);
-	else if (NM_IS_SETTING_CDMA (priv->setting))
-		populate_cdma_ui (self, connection);
-	else
-		g_error ("Invalid setting");
-}
-
-static void
 stuff_changed (GtkWidget *w, gpointer user_data)
 {
 	ce_page_changed (CE_PAGE (user_data));
@@ -258,26 +245,61 @@
 	gtk_entry_set_visibility (priv->puk, active);
 }
 
-CEPageMobile *
-ce_page_mobile_new (NMConnection *connection)
+static void
+finish_setup (CEPageMobile *self, gpointer unused, GError *error, gpointer user_data)
+{
+	CEPage *parent = CE_PAGE (self);
+	CEPageMobilePrivate *priv = CE_PAGE_MOBILE_GET_PRIVATE (self);
+
+	if (error)
+		return;
+
+	if (NM_IS_SETTING_GSM (priv->setting))
+		populate_gsm_ui (self, parent->connection);
+	else if (NM_IS_SETTING_CDMA (priv->setting))
+		populate_cdma_ui (self, parent->connection);
+	else
+		g_assert_not_reached ();
+
+	g_signal_connect (priv->number, "changed", G_CALLBACK (stuff_changed), self);
+	g_signal_connect (priv->username, "changed", G_CALLBACK (stuff_changed), self);
+	g_signal_connect (priv->password, "changed", G_CALLBACK (stuff_changed), self);
+	g_signal_connect (priv->apn, "changed", G_CALLBACK (stuff_changed), self);
+	g_signal_connect (priv->network_id, "changed", G_CALLBACK (stuff_changed), self);
+	g_signal_connect (priv->network_type, "changed", G_CALLBACK (stuff_changed), self);
+	g_signal_connect (priv->pin, "changed", G_CALLBACK (stuff_changed), self);
+	g_signal_connect (priv->puk, "changed", G_CALLBACK (stuff_changed), self);
+
+	g_signal_connect (glade_xml_get_widget (parent->xml, "mobile_show_passwords"),
+	                  "toggled",
+	                  G_CALLBACK (show_passwords),
+	                  self);
+}
+
+CEPage *
+ce_page_mobile_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
 {
 	CEPageMobile *self;
 	CEPageMobilePrivate *priv;
 	CEPage *parent;
+	const char *setting_name = NM_SETTING_GSM_SETTING_NAME;
 
-	self = CE_PAGE_MOBILE (g_object_new (CE_TYPE_PAGE_MOBILE, NULL));
+	self = CE_PAGE_MOBILE (g_object_new (CE_TYPE_PAGE_MOBILE,
+	                                     CE_PAGE_CONNECTION, connection,
+	                                     CE_PAGE_PARENT_WINDOW, parent_window,
+	                                     NULL));
 	parent = CE_PAGE (self);
 
 	parent->xml = glade_xml_new (GLADEDIR "/ce-page-mobile.glade", "MobilePage", NULL);
 	if (!parent->xml) {
-		g_warning ("%s: Couldn't load mobile page glade file.", __func__);
+		g_set_error (error, 0, 0, "%s", _("Could not load mobile broadband user interface."));
 		g_object_unref (self);
 		return NULL;
 	}
 
 	parent->page = glade_xml_get_widget (parent->xml, "MobilePage");
 	if (!parent->page) {
-		g_warning ("%s: Couldn't load mobile page from glade file.", __func__);
+		g_set_error (error, 0, 0, "%s", _("Could not load mobile broadband user interface."));
 		g_object_unref (self);
 		return NULL;
 	}
@@ -289,31 +311,24 @@
 	priv = CE_PAGE_MOBILE_GET_PRIVATE (self);
 
 	priv->setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM);
-	if (!priv->setting)
+	if (!priv->setting) {
 		priv->setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA);
+		setting_name = NM_SETTING_CDMA_SETTING_NAME;
+	}
 
 	if (!priv->setting) {
-		/* FIXME: Support add. */
-		g_warning ("Adding mobile conneciton not supported yet.");
+		g_set_error (error, 0, 0, "%s", _("Unsupported mobile broadband connection type."));
 		g_object_unref (self);
 		return NULL;
 	}
 
-	populate_ui (self, connection);
-
-	g_signal_connect (priv->number, "changed", G_CALLBACK (stuff_changed), self);
-	g_signal_connect (priv->username, "changed", G_CALLBACK (stuff_changed), self);
-	g_signal_connect (priv->password, "changed", G_CALLBACK (stuff_changed), self);
-	g_signal_connect (priv->apn, "changed", G_CALLBACK (stuff_changed), self);
-	g_signal_connect (priv->network_id, "changed", G_CALLBACK (stuff_changed), self);
-	g_signal_connect (priv->network_type, "changed", G_CALLBACK (stuff_changed), self);
-	g_signal_connect (priv->pin, "changed", G_CALLBACK (stuff_changed), self);
-	g_signal_connect (priv->puk, "changed", G_CALLBACK (stuff_changed), self);
-
-	g_signal_connect (glade_xml_get_widget (parent->xml, "mobile_show_passwords"),
-					  "toggled", G_CALLBACK (show_passwords), self);
+	g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
+	if (!ce_page_initialize (parent, setting_name, error)) {
+		g_object_unref (self);
+		return NULL;
+	}
 
-	return self;
+	return CE_PAGE (self);
 }
 
 static const char *

Modified: trunk/src/connection-editor/page-mobile.h
==============================================================================
--- trunk/src/connection-editor/page-mobile.h	(original)
+++ trunk/src/connection-editor/page-mobile.h	Fri Apr  3 13:28:12 2009
@@ -47,6 +47,6 @@
 
 GType ce_page_mobile_get_type (void);
 
-CEPageMobile *ce_page_mobile_new (NMConnection *connection);
+CEPage *ce_page_mobile_new (NMConnection *connection, GtkWindow *parent, GError **error);
 
 #endif  /* __PAGE_MOBILE_H__ */

Modified: trunk/src/connection-editor/page-ppp.c
==============================================================================
--- trunk/src/connection-editor/page-ppp.c	(original)
+++ trunk/src/connection-editor/page-ppp.c	Fri Apr  3 13:28:12 2009
@@ -254,27 +254,37 @@
 	g_signal_connect_swapped (priv->send_ppp_echo, "toggled", G_CALLBACK (ce_page_changed), self);
 }
 
-CEPagePpp *
-ce_page_ppp_new (NMConnection *connection)
+static void
+finish_setup (CEPagePpp *self, gpointer unused, GError *error, gpointer user_data)
+{
+	if (!error)
+		populate_ui (self, CE_PAGE (self)->connection);
+}
+
+CEPage *
+ce_page_ppp_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
 {
 	CEPagePpp *self;
 	CEPagePppPrivate *priv;
 	CEPage *parent;
 	NMSettingConnection *s_con;
 
-	self = CE_PAGE_PPP (g_object_new (CE_TYPE_PAGE_PPP, NULL));
+	self = CE_PAGE_PPP (g_object_new (CE_TYPE_PAGE_PPP,
+	                                  CE_PAGE_CONNECTION, connection,
+	                                  CE_PAGE_PARENT_WINDOW, parent_window,
+	                                  NULL));
 	parent = CE_PAGE (self);
 
 	parent->xml = glade_xml_new (GLADEDIR "/ce-page-ppp.glade", "PppPage", NULL);
 	if (!parent->xml) {
-		g_warning ("%s: Couldn't load ppp page glade file.", __func__);
+		g_set_error (error, 0, 0, "%s", _("Could not load PPP user interface."));
 		g_object_unref (self);
 		return NULL;
 	}
 
 	parent->page = glade_xml_get_widget (parent->xml, "PppPage");
 	if (!parent->page) {
-		g_warning ("%s: Couldn't load ppp page from glade file.", __func__);
+		g_set_error (error, 0, 0, "%s", _("Could not load PPP user interface."));
 		g_object_unref (self);
 		return NULL;
 	}
@@ -297,9 +307,13 @@
 	g_assert (s_con);
 	priv->connection_id = g_strdup (nm_setting_connection_get_id (s_con));
 
-	populate_ui (self, connection);
+	g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
+	if (!ce_page_initialize (parent, NM_SETTING_PPP_SETTING_NAME, error)) {
+		g_object_unref (self);
+		return NULL;
+	}
 
-	return self;
+	return CE_PAGE (self);
 }
 
 static void

Modified: trunk/src/connection-editor/page-ppp.h
==============================================================================
--- trunk/src/connection-editor/page-ppp.h	(original)
+++ trunk/src/connection-editor/page-ppp.h	Fri Apr  3 13:28:12 2009
@@ -47,6 +47,6 @@
 
 GType ce_page_ppp_get_type (void);
 
-CEPagePpp *ce_page_ppp_new (NMConnection *connection);
+CEPage *ce_page_ppp_new (NMConnection *connection, GtkWindow *parent, GError **error);
 
 #endif  /* __PAGE_PPP_H__ */

Modified: trunk/src/connection-editor/page-vpn.c
==============================================================================
--- trunk/src/connection-editor/page-vpn.c	(original)
+++ trunk/src/connection-editor/page-vpn.c	Fri Apr  3 13:28:12 2009
@@ -42,6 +42,9 @@
 typedef struct {
 	NMSettingVPN *setting;
 
+	char *service_type;
+
+	NMVpnPluginUiInterface *plugin;
 	NMVpnPluginUiWidgetInterface *ui;
 
 	gboolean disposed;
@@ -53,17 +56,49 @@
 	ce_page_changed (CE_PAGE (self));
 }
 
-CEPageVpn *
-ce_page_vpn_new (NMConnection *connection)
+static void
+finish_setup (CEPageVpn *self, gpointer unused, GError *error, gpointer user_data)
+{
+	CEPage *parent = CE_PAGE (self);
+	CEPageVpnPrivate *priv = CE_PAGE_VPN_GET_PRIVATE (self);
+	GError *vpn_error = NULL;
+
+	if (error)
+		return;
+
+	g_return_if_fail (priv->plugin != NULL);
+
+	priv->ui = nm_vpn_plugin_ui_interface_ui_factory (priv->plugin, parent->connection, &vpn_error);
+	if (!priv->ui) {
+		g_warning ("Could not load VPN user interface for service '%s': %s.",
+		           priv->service_type,
+		           (vpn_error && vpn_error->message) ? vpn_error->message : "(unknown)");
+		g_error_free (vpn_error);
+		return;
+	}
+	g_signal_connect (priv->ui, "changed", G_CALLBACK (vpn_plugin_changed_cb), self);
+
+	parent->page = GTK_WIDGET (nm_vpn_plugin_ui_widget_interface_get_widget (priv->ui));
+	if (!parent->page) {
+		g_warning ("Could not load VPN user interface for service '%s'.", priv->service_type);
+		return;
+	}
+	g_object_ref_sink (parent->page);
+	gtk_widget_show_all (parent->page);
+}
+
+CEPage *
+ce_page_vpn_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
 {
 	CEPageVpn *self;
 	CEPageVpnPrivate *priv;
 	CEPage *parent;
-	GError *error = NULL;
-	NMVpnPluginUiInterface *plugin;
 	const char *service_type;
 
-	self = CE_PAGE_VPN (g_object_new (CE_TYPE_PAGE_VPN, NULL));
+	self = CE_PAGE_VPN (g_object_new (CE_TYPE_PAGE_VPN,
+	                                  CE_PAGE_CONNECTION, connection,
+	                                  CE_PAGE_PARENT_WINDOW, parent_window,
+	                                  NULL));
 	parent = CE_PAGE (self);
 	priv = CE_PAGE_VPN_GET_PRIVATE (self);
 
@@ -74,35 +109,22 @@
 
 	service_type = nm_setting_vpn_get_service_type (priv->setting);
 	g_assert (service_type);
+	priv->service_type = g_strdup (service_type);
 
-	plugin = vpn_get_plugin_by_service (service_type);
-	if (!plugin) {
-		g_warning ("%s: couldn't find VPN plugin for service '%s'!",
-		           __func__, service_type);
+	priv->plugin = vpn_get_plugin_by_service (service_type);
+	if (!priv->plugin) {
+		g_set_error (error, 0, 0, _("Could not find VPN plugin service for '%s'."), service_type);
 		g_object_unref (self);
 		return NULL;
 	}
 
-	priv->ui = nm_vpn_plugin_ui_interface_ui_factory (plugin, connection, &error);
-	if (!priv->ui) {
-		g_warning ("%s: couldn't create VPN UI for service '%s': %s",
-		           __func__, service_type, error->message);
-		g_error_free (error);
+	g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
+	if (!ce_page_initialize (parent, NM_SETTING_VPN_SETTING_NAME, error)) {
 		g_object_unref (self);
 		return NULL;
 	}
-	g_signal_connect (priv->ui, "changed", G_CALLBACK (vpn_plugin_changed_cb), self);
 
-	parent->page = GTK_WIDGET (nm_vpn_plugin_ui_widget_interface_get_widget (priv->ui));
-	if (!parent->page) {
-		g_warning ("%s: Couldn't load vpn page from the plugin.", __func__);
-		g_object_unref (self);
-		return NULL;
-	}
-	g_object_ref_sink (parent->page);
-	gtk_widget_show_all (parent->page);
-
-	return self;
+	return CE_PAGE (self);
 }
 
 gboolean
@@ -151,6 +173,8 @@
 	if (priv->ui)
 		g_object_unref (priv->ui);
 
+	g_free (priv->service_type);
+
 	G_OBJECT_CLASS (ce_page_vpn_parent_class)->dispose (object);
 }
 

Modified: trunk/src/connection-editor/page-vpn.h
==============================================================================
--- trunk/src/connection-editor/page-vpn.h	(original)
+++ trunk/src/connection-editor/page-vpn.h	Fri Apr  3 13:28:12 2009
@@ -47,7 +47,7 @@
 
 GType ce_page_vpn_get_type (void);
 
-CEPageVpn *ce_page_vpn_new (NMConnection *connection);
+CEPage *ce_page_vpn_new (NMConnection *connection, GtkWindow *parent, GError **error);
 
 gboolean ce_page_vpn_save_secrets (CEPage *page, NMConnection *connection);
 

Modified: trunk/src/connection-editor/page-wired-security.c
==============================================================================
--- trunk/src/connection-editor/page-wired-security.c	(original)
+++ trunk/src/connection-editor/page-wired-security.c	Fri Apr  3 13:28:12 2009
@@ -47,6 +47,8 @@
 	GtkWidget *security_widget;
 	WirelessSecurity *security;
 
+	gboolean initial_have_8021x;
+
 	gboolean disposed;
 } CEPageWiredSecurityPrivate;
 
@@ -65,43 +67,67 @@
 	ce_page_changed (CE_PAGE (user_data));
 }
 
-CEPageWiredSecurity *
-ce_page_wired_security_new (NMConnection *connection)
+static void
+finish_setup (CEPageWiredSecurity *self, gpointer unused, GError *error, gpointer user_data)
+{
+	CEPage *parent = CE_PAGE (self);
+	CEPageWiredSecurityPrivate *priv = CE_PAGE_WIRED_SECURITY_GET_PRIVATE (self);
+	const char *glade_file = GLADEDIR "/applet.glade";
+
+	if (error)
+		return;
+
+	priv->security = (WirelessSecurity *) ws_wpa_eap_new (glade_file, parent->connection);
+	if (!priv->security) {
+		g_warning ("Could not load wired 802.1x user interface.");
+		return;
+	}
+
+	wireless_security_set_changed_notify (priv->security, stuff_changed, self);
+	priv->security_widget = wireless_security_get_widget (priv->security);
+
+	gtk_toggle_button_set_active (priv->enabled, priv->initial_have_8021x);
+	g_signal_connect_swapped (priv->enabled, "toggled", G_CALLBACK (ce_page_changed), self);
+	gtk_widget_set_sensitive (priv->security_widget, priv->initial_have_8021x);
+
+	gtk_box_pack_start (GTK_BOX (parent->page), GTK_WIDGET (priv->enabled), FALSE, TRUE, 12);
+	gtk_box_pack_start (GTK_BOX (parent->page), priv->security_widget, TRUE, TRUE, 0);
+	gtk_widget_show_all (parent->page);
+}
+
+CEPage *
+ce_page_wired_security_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
 {
 	CEPageWiredSecurity *self;
 	CEPage *parent;
 	CEPageWiredSecurityPrivate *priv;
-	const char *glade_file = GLADEDIR "/applet.glade";
-	NMSetting *setting;
 
-	self = CE_PAGE_WIRED_SECURITY (g_object_new (CE_TYPE_PAGE_WIRED_SECURITY, NULL));
+	self = CE_PAGE_WIRED_SECURITY (g_object_new (CE_TYPE_PAGE_WIRED_SECURITY,
+	                                             CE_PAGE_CONNECTION, connection,
+	                                             CE_PAGE_PARENT_WINDOW, parent_window,
+	                                             NULL));
 	parent = CE_PAGE (self);
 	priv = CE_PAGE_WIRED_SECURITY_GET_PRIVATE (self);
 
 	parent->title = g_strdup (_("802.1x Security"));
 	parent->page = gtk_vbox_new (FALSE, 6);
+	g_object_ref_sink (G_OBJECT (parent->page));
 	gtk_container_set_border_width (GTK_CONTAINER (parent->page), 6);
 
-	setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X);
-
-	priv->security = (WirelessSecurity *) ws_wpa_eap_new (glade_file, connection);
-	wireless_security_set_changed_notify (priv->security, stuff_changed, self);
-	priv->security_widget = wireless_security_get_widget (priv->security);
+	if (nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X))
+		priv->initial_have_8021x = TRUE;
 
 	priv->enabled = GTK_TOGGLE_BUTTON (gtk_check_button_new_with_label (_("Use 802.1X security for this connection")));
 	g_signal_connect (priv->enabled, "toggled",
 					  G_CALLBACK (enable_toggled), self);
 
-	gtk_toggle_button_set_active (priv->enabled, setting != NULL);
-	g_signal_connect_swapped (priv->enabled, "toggled", G_CALLBACK (ce_page_changed), self);
-	gtk_widget_set_sensitive (priv->security_widget, setting != NULL);
-
-	gtk_box_pack_start (GTK_BOX (parent->page), GTK_WIDGET (priv->enabled), FALSE, TRUE, 12);
-	gtk_box_pack_start (GTK_BOX (parent->page), priv->security_widget, TRUE, TRUE, 0);
-	g_object_ref_sink (parent->page);
-	gtk_widget_show_all (parent->page);
+	g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
+	if (!ce_page_initialize (parent, NM_SETTING_802_1X_SETTING_NAME, error)) {
+		g_object_unref (self);
+		return NULL;
+	}
 
-	return self;
+	return CE_PAGE (self);
 }
 
 static gboolean
@@ -152,7 +178,9 @@
 		return;
 
 	priv->disposed = TRUE;
-	wireless_security_unref (priv->security);
+
+	if (priv->security)
+		wireless_security_unref (priv->security);
 
 	G_OBJECT_CLASS (ce_page_wired_security_parent_class)->dispose (object);
 }

Modified: trunk/src/connection-editor/page-wired-security.h
==============================================================================
--- trunk/src/connection-editor/page-wired-security.h	(original)
+++ trunk/src/connection-editor/page-wired-security.h	Fri Apr  3 13:28:12 2009
@@ -49,6 +49,6 @@
 
 GType ce_page_wired_security_get_type (void);
 
-CEPageWiredSecurity *ce_page_wired_security_new (NMConnection *connection);
+CEPage *ce_page_wired_security_new (NMConnection *connection, GtkWindow *parent, GError **error);
 
 #endif  /* __PAGE_WIRED_SECURITY_H__ */

Modified: trunk/src/connection-editor/page-wired.c
==============================================================================
--- trunk/src/connection-editor/page-wired.c	(original)
+++ trunk/src/connection-editor/page-wired.c	Fri Apr  3 13:28:12 2009
@@ -136,7 +136,7 @@
 
 	/* Autonegotiate */
 	gtk_toggle_button_set_active (priv->autonegotiate, 
-								  nm_setting_wired_get_auto_negotiate (setting));
+	                              nm_setting_wired_get_auto_negotiate (setting));
 
 	/* MAC address */
 	ce_page_mac_to_entry (nm_setting_wired_get_mac_address (setting), priv->mac);
@@ -151,27 +151,64 @@
 	gtk_spin_button_set_value (priv->mtu, (gdouble) nm_setting_wired_get_mtu (setting));
 }
 
-CEPageWired *
-ce_page_wired_new (NMConnection *connection)
+static void
+finish_setup (CEPageWired *self, gpointer unused, GError *error, gpointer user_data)
+{
+	CEPage *parent = CE_PAGE (self);
+	CEPageWiredPrivate *priv = CE_PAGE_WIRED_GET_PRIVATE (self);
+	GtkWidget *widget;
+
+	if (error)
+		return;
+
+	populate_ui (self);
+
+	g_signal_connect (priv->port, "changed", G_CALLBACK (stuff_changed), self);
+	g_signal_connect (priv->speed, "changed", G_CALLBACK (stuff_changed), self);
+	g_signal_connect (priv->duplex, "toggled", G_CALLBACK (stuff_changed), self);
+	g_signal_connect (priv->autonegotiate, "toggled", G_CALLBACK (stuff_changed), self);
+	g_signal_connect (priv->mtu, "value-changed", G_CALLBACK (stuff_changed), self);
+
+	/* Hide widgets we don't yet support */
+	widget = glade_xml_get_widget (parent->xml, "wired_port_label");
+	gtk_widget_hide (widget);
+	widget = glade_xml_get_widget (parent->xml, "wired_port");
+	gtk_widget_hide (widget);
+
+	widget = glade_xml_get_widget (parent->xml, "wired_speed_label");
+	gtk_widget_hide (widget);
+	widget = glade_xml_get_widget (parent->xml, "wired_speed");
+	gtk_widget_hide (widget);
+
+	widget = glade_xml_get_widget (parent->xml, "wired_duplex");
+	gtk_widget_hide (widget);
+	widget = glade_xml_get_widget (parent->xml, "wired_autonegotiate");
+	gtk_widget_hide (widget);
+}
+
+CEPage *
+ce_page_wired_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
 {
 	CEPageWired *self;
 	CEPageWiredPrivate *priv;
 	CEPage *parent;
-	GtkWidget *widget;
 
-	self = CE_PAGE_WIRED (g_object_new (CE_TYPE_PAGE_WIRED, NULL));
+	self = CE_PAGE_WIRED (g_object_new (CE_TYPE_PAGE_WIRED,
+	                                    CE_PAGE_CONNECTION, connection,
+	                                    CE_PAGE_PARENT_WINDOW, parent_window,
+	                                    NULL));
 	parent = CE_PAGE (self);
 
 	parent->xml = glade_xml_new (GLADEDIR "/ce-page-wired.glade", "WiredPage", NULL);
 	if (!parent->xml) {
-		g_warning ("%s: Couldn't load wired page glade file.", __func__);
+		g_set_error (error, 0, 0, "%s", _("Could not load wired user interface."));
 		g_object_unref (self);
 		return NULL;
 	}
 
 	parent->page = glade_xml_get_widget (parent->xml, "WiredPage");
 	if (!parent->page) {
-		g_warning ("%s: Couldn't load wired page from glade file.", __func__);
+		g_set_error (error, 0, 0, "%s", _("Could not load wired user interface."));
 		g_object_unref (self);
 		return NULL;
 	}
@@ -188,31 +225,13 @@
 		nm_connection_add_setting (connection, NM_SETTING (priv->setting));
 	}
 
-	populate_ui (self);
-
-	g_signal_connect (priv->port, "changed", G_CALLBACK (stuff_changed), self);
-	g_signal_connect (priv->speed, "changed", G_CALLBACK (stuff_changed), self);
-	g_signal_connect (priv->duplex, "toggled", G_CALLBACK (stuff_changed), self);
-	g_signal_connect (priv->autonegotiate, "toggled", G_CALLBACK (stuff_changed), self);
-	g_signal_connect (priv->mtu, "value-changed", G_CALLBACK (stuff_changed), self);
-
-	/* Hide widgets we don't yet support */
-	widget = glade_xml_get_widget (parent->xml, "wired_port_label");
-	gtk_widget_hide (widget);
-	widget = glade_xml_get_widget (parent->xml, "wired_port");
-	gtk_widget_hide (widget);
-
-	widget = glade_xml_get_widget (parent->xml, "wired_speed_label");
-	gtk_widget_hide (widget);
-	widget = glade_xml_get_widget (parent->xml, "wired_speed");
-	gtk_widget_hide (widget);
-
-	widget = glade_xml_get_widget (parent->xml, "wired_duplex");
-	gtk_widget_hide (widget);
-	widget = glade_xml_get_widget (parent->xml, "wired_autonegotiate");
-	gtk_widget_hide (widget);
+	g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
+	if (!ce_page_initialize (parent, NULL, error)) {
+		g_object_unref (self);
+		return NULL;
+	}
 
-	return self;
+	return CE_PAGE (self);
 }
 
 static void

Modified: trunk/src/connection-editor/page-wired.h
==============================================================================
--- trunk/src/connection-editor/page-wired.h	(original)
+++ trunk/src/connection-editor/page-wired.h	Fri Apr  3 13:28:12 2009
@@ -47,7 +47,7 @@
 
 GType ce_page_wired_get_type (void);
 
-CEPageWired *ce_page_wired_new (NMConnection *connection);
+CEPage *ce_page_wired_new (NMConnection *connection, GtkWindow *parent, GError **error);
 
 #endif  /* __PAGE_WIRED_H__ */
 

Modified: trunk/src/connection-editor/page-wireless-security.c
==============================================================================
--- trunk/src/connection-editor/page-wireless-security.c	(original)
+++ trunk/src/connection-editor/page-wireless-security.c	Fri Apr  3 13:28:12 2009
@@ -183,13 +183,13 @@
 	wireless_security_unref (sec);
 }
 
-CEPageWirelessSecurity *
-ce_page_wireless_security_new (NMConnection *connection)
+static void
+finish_setup (CEPageWirelessSecurity *self, gpointer unused, GError *error, gpointer user_data)
 {
-	CEPageWirelessSecurity *self;
-	CEPage *parent;
+	CEPage *parent = CE_PAGE (self);
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wireless_sec;
+	NMConnection *connection = parent->connection;
 	gboolean is_adhoc = FALSE;
 	GtkListStore *sec_model;
 	GtkTreeIter iter;
@@ -202,34 +202,11 @@
 	const char *glade_file = GLADEDIR "/applet.glade";
 	GtkComboBox *combo;
 
-	self = CE_PAGE_WIRELESS_SECURITY (g_object_new (CE_TYPE_PAGE_WIRELESS_SECURITY, NULL));
-	parent = CE_PAGE (self);
+	if (error)
+		return;
 
 	s_wireless = NM_SETTING_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS));
-	if (!s_wireless) {
-		g_warning ("%s: Connection didn't have a wireless setting!", __func__);
-		g_object_unref (self);
-		return NULL;
-	}
-
-	parent->xml = glade_xml_new (GLADEDIR "/ce-page-wireless-security.glade", "WirelessSecurityPage", NULL);
-	if (!parent->xml) {
-		g_warning ("%s: Couldn't load wireless security page glade file.", __func__);
-		g_object_unref (self);
-		return NULL;
-	}
-
-	parent->page = glade_xml_get_widget (parent->xml, "WirelessSecurityPage");
-	if (!parent->page) {
-		g_warning ("%s: Couldn't load wireless security page from glade file.", __func__);
-		g_object_unref (self);
-		return NULL;
-	}
-	g_object_ref_sink (parent->page);
-
-	parent->title = g_strdup (_("Wireless Security"));
-
-	self->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+	g_assert (s_wireless);
 
 	combo = GTK_COMBO_BOX (glade_xml_get_widget (parent->xml, "wireless_security_combo"));
 
@@ -355,8 +332,83 @@
 	g_signal_connect (combo, "changed",
 	                  G_CALLBACK (wireless_security_combo_changed),
 	                  self);
+}
+
+CEPage *
+ce_page_wireless_security_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
+{
+	CEPageWirelessSecurity *self;
+	CEPage *parent;
+	NMSettingWireless *s_wireless;
+	NMSettingWirelessSecurity *s_wsec = NULL;
+	const char *setting_name = NULL;
+	NMUtilsSecurityType default_type = NMU_SEC_NONE;
+	const char *security;
+
+	self = CE_PAGE_WIRELESS_SECURITY (g_object_new (CE_TYPE_PAGE_WIRELESS_SECURITY,
+	                                                CE_PAGE_CONNECTION, connection,
+	                                                CE_PAGE_PARENT_WINDOW, parent_window,
+	                                                NULL));
+	parent = CE_PAGE (self);
+
+	s_wireless = NM_SETTING_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS));
+	if (!s_wireless) {
+		g_set_error (error, 0, 0, "%s", _("Could not load WiFi security user interface; missing WiFi setting."));
+		g_object_unref (self);
+		return NULL;
+	}
+
+	parent->xml = glade_xml_new (GLADEDIR "/ce-page-wireless-security.glade", "WirelessSecurityPage", NULL);
+	if (!parent->xml) {
+		g_set_error (error, 0, 0, "%s", _("Could not load WiFi security user interface."));
+		g_object_unref (self);
+		return NULL;
+	}
+
+	parent->page = glade_xml_get_widget (parent->xml, "WirelessSecurityPage");
+	if (!parent->page) {
+		g_set_error (error, 0, 0, "%s", _("Could not load WiFi security user interface."));
+		g_object_unref (self);
+		return NULL;
+	}
+	g_object_ref_sink (parent->page);
+
+	parent->title = g_strdup (_("Wireless Security"));
+
+	self->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+	g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
+
+	s_wsec = NM_SETTING_WIRELESS_SECURITY (nm_connection_get_setting (connection, 
+	                                       NM_TYPE_SETTING_WIRELESS_SECURITY));
+
+	security = nm_setting_wireless_get_security (s_wireless);
+	if (!security || strcmp (security, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME))
+		s_wsec = NULL;
+	if (s_wsec)
+		default_type = get_default_type_for_security (s_wsec);
+
+	/* Get secrets if the connection is not 802.1x enabled */
+	if (   default_type == NMU_SEC_STATIC_WEP
+	    || default_type == NMU_SEC_LEAP
+	    || default_type == NMU_SEC_WPA_PSK
+	    || default_type == NMU_SEC_WPA2_PSK) {
+		setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
+	}
+
+	/* Or if it is 802.1x enabled */
+	if (   default_type == NMU_SEC_DYNAMIC_WEP
+	    || default_type == NMU_SEC_WPA_ENTERPRISE
+	    || default_type == NMU_SEC_WPA2_ENTERPRISE) {
+		setting_name = NM_SETTING_802_1X_SETTING_NAME;
+	}
+
+	if (!ce_page_initialize (parent, setting_name, error)) {
+		g_object_unref (self);
+		return NULL;
+	}
 
-	return self;
+	return CE_PAGE (self);
 }
 
 static void

Modified: trunk/src/connection-editor/page-wireless-security.h
==============================================================================
--- trunk/src/connection-editor/page-wireless-security.h	(original)
+++ trunk/src/connection-editor/page-wireless-security.h	Fri Apr  3 13:28:12 2009
@@ -54,7 +54,7 @@
 
 GType ce_page_wireless_security_get_type (void);
 
-CEPageWirelessSecurity *ce_page_wireless_security_new (NMConnection *connection);
+CEPage *ce_page_wireless_security_new (NMConnection *connection, GtkWindow *parent, GError **error);
 
 #endif  /* __PAGE_WIRELESS_SECURITY_H__ */
 

Modified: trunk/src/connection-editor/page-wireless.c
==============================================================================
--- trunk/src/connection-editor/page-wireless.c	(original)
+++ trunk/src/connection-editor/page-wireless.c	Fri Apr  3 13:28:12 2009
@@ -295,29 +295,64 @@
 	gtk_spin_button_set_value (priv->mtu, (gdouble) nm_setting_wireless_get_mtu (setting));
 }
 
-CEPageWireless *
-ce_page_wireless_new (NMConnection *connection)
+static void
+finish_setup (CEPageWireless *self, gpointer unused, GError *error, gpointer user_data)
+{
+	CEPage *parent = CE_PAGE (self);
+	GtkWidget *widget;
+
+	if (error)
+		return;
+
+	populate_ui (self);
+
+	/* Hide widgets we don't yet support */
+	widget = glade_xml_get_widget (parent->xml, "wireless_band_label");
+	gtk_widget_hide (widget);
+	widget = glade_xml_get_widget (parent->xml, "wireless_band");
+	gtk_widget_hide (widget);
+
+	widget = glade_xml_get_widget (parent->xml, "wireless_channel_label");
+	gtk_widget_hide (widget);
+	widget = glade_xml_get_widget (parent->xml, "wireless_channel");
+	gtk_widget_hide (widget);
+
+	widget = glade_xml_get_widget (parent->xml, "wireless_tx_power_label");
+	gtk_widget_hide (widget);
+	widget = glade_xml_get_widget (parent->xml, "wireless_tx_power_hbox");
+	gtk_widget_hide (widget);
+
+	widget = glade_xml_get_widget (parent->xml, "wireless_rate_label");
+	gtk_widget_hide (widget);
+	widget = glade_xml_get_widget (parent->xml, "wireless_rate_hbox");
+	gtk_widget_hide (widget);
+}
+
+CEPage *
+ce_page_wireless_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
 {
 	CEPageWireless *self;
 	CEPageWirelessPrivate *priv;
 	CEPage *parent;
-	GtkWidget *widget;
 
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
-	self = CE_PAGE_WIRELESS (g_object_new (CE_TYPE_PAGE_WIRELESS, NULL));
+	self = CE_PAGE_WIRELESS (g_object_new (CE_TYPE_PAGE_WIRELESS,
+	                                       CE_PAGE_CONNECTION, connection,
+	                                       CE_PAGE_PARENT_WINDOW, parent_window,
+	                                       NULL));
 	parent = CE_PAGE (self);
 
 	parent->xml = glade_xml_new (GLADEDIR "/ce-page-wireless.glade", "WirelessPage", NULL);
 	if (!parent->xml) {
-		g_warning ("%s: Couldn't load wireless page glade file.", __func__);
+		g_set_error (error, 0, 0, "%s", _("Could not load WiFi user interface."));
 		g_object_unref (self);
 		return NULL;
 	}
 
 	parent->page = glade_xml_get_widget (parent->xml, "WirelessPage");
 	if (!parent->page) {
-		g_warning ("%s: Couldn't load wireless page from glade file.", __func__);
+		g_set_error (error, 0, 0, "%s", _("Could not load WiFi user interface."));
 		g_object_unref (self);
 		return NULL;
 	}
@@ -334,30 +369,13 @@
 		nm_connection_add_setting (connection, NM_SETTING (priv->setting));
 	}
 
-	populate_ui (self);
-
-	/* Hide widgets we don't yet support */
-	widget = glade_xml_get_widget (parent->xml, "wireless_band_label");
-	gtk_widget_hide (widget);
-	widget = glade_xml_get_widget (parent->xml, "wireless_band");
-	gtk_widget_hide (widget);
-
-	widget = glade_xml_get_widget (parent->xml, "wireless_channel_label");
-	gtk_widget_hide (widget);
-	widget = glade_xml_get_widget (parent->xml, "wireless_channel");
-	gtk_widget_hide (widget);
-
-	widget = glade_xml_get_widget (parent->xml, "wireless_tx_power_label");
-	gtk_widget_hide (widget);
-	widget = glade_xml_get_widget (parent->xml, "wireless_tx_power_hbox");
-	gtk_widget_hide (widget);
-
-	widget = glade_xml_get_widget (parent->xml, "wireless_rate_label");
-	gtk_widget_hide (widget);
-	widget = glade_xml_get_widget (parent->xml, "wireless_rate_hbox");
-	gtk_widget_hide (widget);
+	g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
+	if (!ce_page_initialize (parent, NULL, error)) {
+		g_object_unref (self);
+		return NULL;
+	}
 
-	return self;
+	return CE_PAGE (self);
 }
 
 GByteArray *

Modified: trunk/src/connection-editor/page-wireless.h
==============================================================================
--- trunk/src/connection-editor/page-wireless.h	(original)
+++ trunk/src/connection-editor/page-wireless.h	Fri Apr  3 13:28:12 2009
@@ -47,7 +47,7 @@
 
 GType ce_page_wireless_get_type (void);
 
-CEPageWireless *ce_page_wireless_new (NMConnection *connection);
+CEPage *ce_page_wireless_new (NMConnection *connection, GtkWindow *parent, GError **error);
 
 /* Caller must free returned array */
 GByteArray *ce_page_wireless_get_ssid (CEPageWireless *self);

Added: trunk/src/connection-editor/polkit-helpers.c
==============================================================================
--- (empty file)
+++ trunk/src/connection-editor/polkit-helpers.c	Fri Apr  3 13:28:12 2009
@@ -0,0 +1,79 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Connection editor -- Connection editor for NetworkManager
+ *
+ * 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.
+ *
+ * (C) Copyright 2008 Novell, Inc.
+ * (C) Copyright 2008 - 2009 Red Hat, Inc.
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
+#include <gdk/gdkx.h>
+
+#include "polkit-helpers.h"
+
+gboolean
+pk_helper_is_permission_denied_error (GError *error)
+{
+	return    dbus_g_error_has_name (error, "org.freedesktop.NetworkManagerSettings.Connection.NotPrivileged")
+	       || dbus_g_error_has_name (error, "org.freedesktop.NetworkManagerSettings.System.NotPrivileged");
+}
+
+gboolean
+pk_helper_obtain_auth (GError *pk_error,
+                       GtkWindow *parent,
+                       PolKitGnomeAuthCB callback,
+                       gpointer user_data,
+                       GError **error)
+{
+	PolKitAction *pk_action;
+	char **tokens;
+	gboolean success = FALSE;
+	guint xid = 0;
+
+	tokens = g_strsplit (pk_error->message, " ", 2);
+	if (g_strv_length (tokens) != 2) {
+		g_set_error (error, 0, 0, "%s", _("PolicyKit authorization was malformed."));
+		goto out;
+	}
+
+        pk_action = polkit_action_new ();
+	if (!pk_action) {
+		g_set_error (error, 0, 0, "%s", _("PolicyKit authorization could not be created."));
+		goto out;
+	}
+
+        if (!polkit_action_set_action_id (pk_action, tokens[0])) {
+                polkit_action_unref (pk_action);
+                pk_action = NULL;
+		g_set_error (error, 0, 0, "%s", _("PolicyKit authorization could not be created; invalid action ID."));
+		goto out;
+        }
+
+	if (parent)
+		xid = gdk_x11_drawable_get_xid (GDK_DRAWABLE (GTK_WIDGET (parent)->window));
+	success = polkit_gnome_auth_obtain (pk_action, xid, getpid (), callback, user_data, error);
+	polkit_action_unref (pk_action);
+
+out:
+	g_strfreev (tokens);
+	return success;
+}
+

Added: trunk/src/connection-editor/polkit-helpers.h
==============================================================================
--- (empty file)
+++ trunk/src/connection-editor/polkit-helpers.h	Fri Apr  3 13:28:12 2009
@@ -0,0 +1,41 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Connection editor -- Connection editor for NetworkManager
+ *
+ * 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.
+ *
+ * (C) Copyright 2008 Novell, Inc.
+ * (C) Copyright 2008 - 2009 Red Hat, Inc.
+ */
+
+#ifndef _PK_HELPERS_H_
+#define _PK_HELPERS_H_
+
+#include <glib.h>
+#ifdef NO_POLKIT_GNOME
+#include "polkit-gnome.h"
+#else
+#include <polkit-gnome/polkit-gnome.h>
+#endif
+
+gboolean pk_helper_is_permission_denied_error (GError *error);
+
+gboolean pk_helper_obtain_auth (GError *pk_error,
+                                GtkWindow *parent,
+                                PolKitGnomeAuthCB callback,
+                                gpointer user_data,
+                                GError **error);
+
+#endif  /* _PK_HELPERS_H_ */
+

Modified: trunk/src/marshallers/nma-marshal.list
==============================================================================
--- trunk/src/marshallers/nma-marshal.list	(original)
+++ trunk/src/marshallers/nma-marshal.list	Fri Apr  3 13:28:12 2009
@@ -2,3 +2,6 @@
 VOID:STRING,STRING,STRING
 VOID:STRING,POINTER,BOOLEAN,POINTER
 VOID:OBJECT,STRING,POINTER,BOOLEAN,POINTER
+VOID:POINTER,POINTER
+VOID:INT,POINTER
+



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