Commit 291f1f12 authored by Tambet Ingo's avatar Tambet Ingo Committed by Tambet Ingo
Browse files

src/connection-editor/ce-page.c src/connection-editor/ce-page.h

2008-06-20  Tambet Ingo  <tambet@gmail.com>

	* src/connection-editor/ce-page.c
	src/connection-editor/ce-page.h
	src/connection-editor/nm-connection-editor.c
	src/connection-editor/nm-connection-editor.h
	src/connection-editor/nm-connection-list.c
	src/connection-editor/page-dsl.c
	src/connection-editor/page-ip4.c
	src/connection-editor/page-mobile.c
	src/connection-editor/page-ppp.c
	src/connection-editor/page-vpn.c
	src/connection-editor/page-wired-security.c
	src/connection-editor/page-wired.c
	src/connection-editor/page-wireless-security.c
	src/connection-editor/page-wireless-security.h
	src/connection-editor/page-wireless.c

	Use a copy of the real connection in the connection editor. Fixes issues
	where the connection is updated but writing it fails for some reason.
	Keep the connection that's been edited updated after every UI change so
	that pages can act on changes to other pages.

svn path=/trunk/; revision=760
parent e1a21dbb
2008-06-20 Tambet Ingo <tambet@gmail.com>
* src/connection-editor/ce-page.c
src/connection-editor/ce-page.h
src/connection-editor/nm-connection-editor.c
src/connection-editor/nm-connection-editor.h
src/connection-editor/nm-connection-list.c
src/connection-editor/page-dsl.c
src/connection-editor/page-ip4.c
src/connection-editor/page-mobile.c
src/connection-editor/page-ppp.c
src/connection-editor/page-vpn.c
src/connection-editor/page-wired-security.c
src/connection-editor/page-wired.c
src/connection-editor/page-wireless-security.c
src/connection-editor/page-wireless-security.h
src/connection-editor/page-wireless.c
Use a copy of the real connection in the connection editor. Fixes issues
where the connection is updated but writing it fails for some reason.
Keep the connection that's been edited updated after every UI change so
that pages can act on changes to other pages.
2008-06-17 Dan Williams <dcbw@redhat.com>
* src/vpn-properties/*
......
......@@ -39,20 +39,17 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
gboolean
ce_page_validate (CEPage *self, GError **error)
ce_page_validate (CEPage *self, NMConnection *connection, GError **error)
{
g_return_val_if_fail (CE_IS_PAGE (self), FALSE);
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
if (CE_PAGE_GET_CLASS (self)->validate)
return CE_PAGE_GET_CLASS (self)->validate (self, error);
return CE_PAGE_GET_CLASS (self)->validate (self, connection, error);
return TRUE;
}
void
ce_page_update_connection (CEPage *self, NMConnection *connection)
{
CE_PAGE_GET_CLASS (self)->update_connection (self, connection);
}
void
ce_page_mac_to_entry (GByteArray *mac, GtkEntry *entry)
{
......
......@@ -53,8 +53,7 @@ typedef struct {
GObjectClass parent;
/* Virtual functions */
gboolean (*validate) (CEPage *self, GError **error);
void (*update_connection) (CEPage *self, NMConnection *connection);
gboolean (*validate) (CEPage *self, NMConnection *connection, GError **error);
/* Signals */
void (*changed) (CEPage *self);
......@@ -66,9 +65,7 @@ GtkWidget * ce_page_get_page (CEPage *self);
const char * ce_page_get_title (CEPage *self);
gboolean ce_page_validate (CEPage *self, GError **error);
void ce_page_update_connection (CEPage *self, NMConnection *connection);
gboolean ce_page_validate (CEPage *self, NMConnection *connection, GError **error);
void ce_page_changed (CEPage *self);
......
......@@ -71,7 +71,7 @@ enum {
static guint editor_signals[EDITOR_LAST_SIGNAL] = { 0 };
static void nm_connection_editor_set_connection (NMConnectionEditor *editor,
NMExportedConnection *exported);
NMConnection *connection);
static void
dialog_response_cb (GtkDialog *dialog, guint response, gpointer user_data)
......@@ -147,7 +147,7 @@ connection_editor_validate (NMConnectionEditor *editor)
for (iter = editor->pages; iter; iter = g_slist_next (iter)) {
GError *error = NULL;
if (!ce_page_validate (CE_PAGE (iter->data), &error)) {
if (!ce_page_validate (CE_PAGE (iter->data), editor->connection, &error)) {
/* FIXME: use the error to indicate which UI widgets are invalid */
if (error)
g_error_free (error);
......@@ -233,8 +233,8 @@ dispose (GObject *object)
g_slist_free (editor->pages);
editor->pages = NULL;
if (editor->exported)
g_object_unref (editor->exported);
if (editor->connection)
g_object_unref (editor->connection);
gtk_widget_destroy (editor->dialog);
g_object_unref (editor->xml);
......@@ -262,24 +262,24 @@ nm_connection_editor_class_init (NMConnectionEditorClass *klass)
}
NMConnectionEditor *
nm_connection_editor_new (NMExportedConnection *exported)
nm_connection_editor_new (NMConnection *connection)
{
NMConnectionEditor *editor;
g_return_val_if_fail (NM_IS_EXPORTED_CONNECTION (exported), NULL);
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
editor = g_object_new (NM_TYPE_CONNECTION_EDITOR, NULL);
nm_connection_editor_set_connection (editor, exported);
nm_connection_editor_set_connection (editor, connection);
return editor;
}
NMExportedConnection *
NMConnection *
nm_connection_editor_get_connection (NMConnectionEditor *editor)
{
g_return_val_if_fail (NM_IS_CONNECTION_EDITOR (editor), NULL);
return editor->exported;
return editor->connection;
}
gint
......@@ -356,20 +356,18 @@ add_page (NMConnectionEditor *editor, CEPage *page)
}
static void
nm_connection_editor_set_connection (NMConnectionEditor *editor, NMExportedConnection *exported)
nm_connection_editor_set_connection (NMConnectionEditor *editor, NMConnection *connection)
{
NMSettingConnection *s_con;
g_return_if_fail (NM_IS_CONNECTION_EDITOR (editor));
g_return_if_fail (NM_IS_EXPORTED_CONNECTION (exported));
g_return_if_fail (NM_IS_CONNECTION (connection));
/* clean previous connection */
if (editor->exported)
g_object_unref (editor->exported);
editor->exported = g_object_ref (exported);
editor->connection = nm_exported_connection_get_connection (exported);
if (editor->connection)
g_object_unref (editor->connection);
editor->connection = g_object_ref (connection);
nm_connection_editor_update_title (editor);
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (editor->connection, NM_TYPE_SETTING_CONNECTION));
......@@ -380,15 +378,8 @@ nm_connection_editor_set_connection (NMConnectionEditor *editor, NMExportedConne
add_page (editor, CE_PAGE (ce_page_wired_security_new (editor->connection)));
add_page (editor, CE_PAGE (ce_page_ip4_new (editor->connection)));
} else if (!strcmp (s_con->type, NM_SETTING_WIRELESS_SETTING_NAME)) {
CEPageWireless *wireless_page;
CEPageWirelessSecurity *wireless_security_page;
wireless_page = ce_page_wireless_new (editor->connection);
add_page (editor, CE_PAGE (wireless_page));
wireless_security_page = ce_page_wireless_security_new (editor->connection, wireless_page);
add_page (editor, CE_PAGE (wireless_security_page));
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)));
} else if (!strcmp (s_con->type, NM_SETTING_VPN_SETTING_NAME)) {
add_page (editor, CE_PAGE (ce_page_vpn_new (editor->connection)));
......@@ -417,12 +408,6 @@ nm_connection_editor_present (NMConnectionEditor *editor)
gtk_window_present (GTK_WINDOW (editor->dialog));
}
static void
update_one_page (gpointer data, gpointer user_data)
{
ce_page_update_connection (CE_PAGE (data), NM_CONNECTION (user_data));
}
static void
connection_editor_update_connection (NMConnectionEditor *editor)
{
......@@ -448,8 +433,6 @@ connection_editor_update_connection (NMConnectionEditor *editor)
nm_connection_set_scope (editor->connection, NM_CONNECTION_SCOPE_SYSTEM);
else
nm_connection_set_scope (editor->connection, NM_CONNECTION_SCOPE_USER);
g_slist_foreach (editor->pages, update_one_page, editor->connection);
}
static void
......
......@@ -25,9 +25,7 @@
#include <glib-object.h>
#include <glade/glade-xml.h>
#include <gtk/gtksizegroup.h>
#include <gtk/gtkspinbutton.h>
#include <gconf/gconf-client.h>
#include <nm-settings.h>
#define NM_TYPE_CONNECTION_EDITOR (nm_connection_editor_get_type ())
......@@ -38,7 +36,6 @@ typedef struct {
GObject parent;
/* private data */
NMExportedConnection *exported;
NMConnection *connection;
GSList *pages;
......@@ -55,11 +52,11 @@ typedef struct {
} NMConnectionEditorClass;
GType nm_connection_editor_get_type (void);
NMConnectionEditor *nm_connection_editor_new (NMExportedConnection *exported);
NMConnectionEditor *nm_connection_editor_new (NMConnection *connection);
void nm_connection_editor_present (NMConnectionEditor *editor);
void nm_connection_editor_run (NMConnectionEditor *editor);
NMExportedConnection *nm_connection_editor_get_connection (NMConnectionEditor *editor);
NMConnection *nm_connection_editor_get_connection (NMConnectionEditor *editor);
gint ce_spin_output_with_default (GtkSpinButton *spin, gpointer user_data);
......
......@@ -83,23 +83,6 @@ typedef struct {
GtkWidget *button;
} ActionInfo;
enum {
NM_MODIFY_CONNECTION_ADD,
NM_MODIFY_CONNECTION_REMOVE,
NM_MODIFY_CONNECTION_UPDATE
};
typedef void (*NMExportedConnectionChangedFn) (NMConnectionList *list,
NMExportedConnection *exported,
gboolean success,
gpointer user_data);
static void modify_connection (NMConnectionList *self,
NMExportedConnection *exported,
guint action,
NMExportedConnectionChangedFn callback,
gpointer user_data);
static void
show_error_dialog (const gchar *format, ...)
{
......@@ -294,25 +277,81 @@ update_connection_row (GtkListStore *store,
g_free (last_used);
}
/**********************************************/
/* 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,
PolKitGnomeAuthCB callback,
gpointer user_data)
{
PolKitAction *pk_action;
char **tokens;
GError *error;
guint xid;
pid_t pid;
gboolean success = FALSE;
tokens = g_strsplit (pk_error->message, " ", 2);
if (g_strv_length (tokens) != 2) {
g_warning ("helper return string malformed");
g_strfreev (tokens);
return FALSE;
}
pk_action = polkit_action_new ();
polkit_action_set_action_id (pk_action, tokens[0]);
g_strfreev (tokens);
xid = 0;
pid = getpid ();
error = NULL;
success = polkit_gnome_auth_obtain (pk_action, xid, pid, callback, user_data, &error);
if (error) {
g_warning ("Could not grant permssion: %s", error->message);
g_error_free (error);
}
return success;
}
/**********************************************/
/* Connection removing */
typedef void (*ConnectionRemovedFn) (NMExportedConnection *exported,
gboolean success,
gpointer user_data);
typedef struct {
NMConnectionList *list;
NMExportedConnection *exported;
guint action;
NMExportedConnectionChangedFn callback;
gpointer callback_data;
} ModifyConnectionInfo;
ConnectionRemovedFn callback;
gpointer user_data;
} ConnectionRemoveInfo;
static void remove_connection (NMExportedConnection *exported,
ConnectionRemovedFn callback,
gpointer user_data);
static void
modify_connection_auth_cb (PolKitAction *action,
gboolean gained_privilege,
GError *error,
gpointer user_data)
remove_connection_cb (PolKitAction *action,
gboolean gained_privilege,
GError *error,
gpointer user_data)
{
ModifyConnectionInfo *info = (ModifyConnectionInfo *) user_data;
ConnectionRemoveInfo *info = (ConnectionRemoveInfo *) user_data;
gboolean done = TRUE;
if (gained_privilege) {
modify_connection (info->list, info->exported, info->action, info->callback, info->callback_data);
remove_connection (info->exported, info->callback, info->user_data);
done = FALSE;
} else if (error) {
show_error_dialog (_("Could not obtain required privileges: %s."), error->message);
......@@ -321,122 +360,308 @@ modify_connection_auth_cb (PolKitAction *action,
show_error_dialog (_("Could not remove system connection: permission denied."));
if (done && info->callback)
info->callback (info->list, info->exported, FALSE, info->callback_data);
info->callback (info->exported, FALSE, info->user_data);
g_object_unref (info->exported);
g_free (info);
g_slice_free (ConnectionRemoveInfo, info);
}
static void
modify_connection (NMConnectionList *self,
NMExportedConnection *exported,
guint action,
NMExportedConnectionChangedFn callback,
remove_connection (NMExportedConnection *exported,
ConnectionRemovedFn callback,
gpointer user_data)
{
const char *error_str;
GError *error = NULL;
gboolean success;
success = nm_exported_connection_delete (exported, &error);
if (!success) {
gboolean auth_pending = FALSE;
if (is_permission_denied_error (error)) {
ConnectionRemoveInfo *info;
info = g_slice_new (ConnectionRemoveInfo);
info->exported = g_object_ref (exported);
info->callback = callback;
info->user_data = user_data;
auth_pending = obtain_auth (error, remove_connection_cb, info);
if (!auth_pending) {
g_object_unref (info->exported);
g_slice_free (ConnectionRemoveInfo, info);
}
} else
show_error_dialog (_("Removing connection failed: %s."), error->message);
g_error_free (error);
if (auth_pending)
return;
}
if (callback)
callback (exported, success, user_data);
}
/**********************************************/
/* Connection adding */
typedef void (*ConnectionAddedFn) (NMExportedConnection *exported,
gboolean success,
gpointer user_data);
typedef struct {
NMConnectionList *list;
NMConnection *connection;
GHashTable *settings;
GError *err = NULL;
ConnectionAddedFn callback;
gpointer user_data;
} ConnectionAddInfo;
static void add_connection (NMConnectionList *self,
NMConnection *connection,
ConnectionAddedFn callback,
gpointer user_data);
static void
add_connection_cb (PolKitAction *action,
gboolean gained_privilege,
GError *error,
gpointer user_data)
{
ConnectionAddInfo *info = (ConnectionAddInfo *) user_data;
gboolean done = TRUE;
if (gained_privilege) {
add_connection (info->list, info->connection, info->callback, info->user_data);
done = FALSE;
} else if (error) {
show_error_dialog (_("Could not obtain required privileges: %s."), error->message);
g_error_free (error);
} else
show_error_dialog (_("Could not add system connection: permission denied."));
if (done && info->callback)
info->callback (NULL, FALSE, info->user_data);
g_object_unref (info->connection);
g_slice_free (ConnectionAddInfo, info);
}
static void
add_connection (NMConnectionList *self,
NMConnection *connection,
ConnectionAddedFn callback,
gpointer user_data)
{
NMExportedConnection *exported = NULL;
gboolean success;
gboolean done = FALSE;
switch (action) {
case NM_MODIFY_CONNECTION_ADD:
error_str = _("Adding connection failed");
if (nm_connection_get_scope (connection) == NM_CONNECTION_SCOPE_SYSTEM) {
GError *error = NULL;
connection = nm_exported_connection_get_connection (exported);
if (nm_connection_get_scope (connection) == NM_CONNECTION_SCOPE_SYSTEM)
success = nm_dbus_settings_system_add_connection (self->system_settings, connection, &err);
else {
NMExportedConnection *new_connection;
new_connection = (NMExportedConnection *) nma_gconf_settings_add_connection (self->gconf_settings, connection);
if (new_connection) {
exported = new_connection;
success = TRUE;
success = nm_dbus_settings_system_add_connection (self->system_settings, connection, &error);
if (!success) {
gboolean pending_auth = FALSE;
if (is_permission_denied_error (error)) {
ConnectionAddInfo *info;
info = g_slice_new (ConnectionAddInfo);
info->list = self;
info->connection = g_object_ref (connection);
info->callback = callback;
info->user_data = user_data;
pending_auth = obtain_auth (error, add_connection_cb, info);
if (!pending_auth) {
g_object_unref (info->connection);
g_slice_free (ConnectionAddInfo, info);
}
} else
success = FALSE;
show_error_dialog (_("Adding connection failed: %s."), error->message);
g_error_free (error);
if (pending_auth)
return;
}
break;
case NM_MODIFY_CONNECTION_REMOVE:
error_str = _("Removing connection failed");
success = nm_exported_connection_delete (exported, &err);
break;
case NM_MODIFY_CONNECTION_UPDATE:
error_str = _("Updating connection failed");
settings = nm_connection_to_hash (nm_exported_connection_get_connection (exported));
success = nm_exported_connection_update (exported, settings, &err);
g_hash_table_destroy (settings);
break;
default:
g_warning ("Invalid action '%d' in %s", action, __func__);
return;
} else {
exported = (NMExportedConnection *) nma_gconf_settings_add_connection (self->gconf_settings, connection);
success = exported != NULL;
}
if (success)
done = TRUE;
if (callback)
callback (exported, success, user_data);
if (err && (dbus_g_error_has_name (err, "org.freedesktop.NetworkManagerSettings.Connection.NotPrivileged") ||
dbus_g_error_has_name (err, "org.freedesktop.NetworkManagerSettings.System.NotPrivileged"))) {
if (exported)
g_object_unref (exported);
}
ModifyConnectionInfo *info;
PolKitAction *pk_action;
char **tokens;
guint xid;
pid_t pid;
/**********************************************/
/* Connection updating */
tokens = g_strsplit (err->message, " ", 2);
if (g_strv_length (tokens) != 2) {
g_warning ("helper return string malformed");
g_strfreev (tokens);
goto out;
}
typedef void (*ConnectionUpdatedFn) (NMConnectionList *list,
gboolean success,
gpointer user_data);
pk_action = polkit_action_new ();
polkit_action_set_action_id (pk_action, tokens[0]);
g_strfreev (tokens);
typedef struct {
NMConnectionList *list;
NMExportedConnection *original;
NMConnection *modified;
ConnectionUpdatedFn callback;
gpointer user_data;
NMExportedConnection *added_connection;
} ConnectionUpdateInfo;
static void update_connection (NMConnectionList *list,
NMExportedConnection *original,
NMConnection *modified,
ConnectionUpdatedFn callback,
gpointer user_data);
xid = 0;
pid = getpid ();
g_error_free (err);
err = NULL;
static void
connection_update_done (ConnectionUpdateInfo *info, gboolean success)
{
if (info->callback)
info->callback (info->list, success, info->user_data);
info = g_new (ModifyConnectionInfo, 1);
info->list = self;
info->exported = g_object_ref (exported);
info->action = action;
info->callback = callback;
info->callback_data = user_data;
g_object_unref (info->original);
g_object_unref (info->modified);
if (info->added_connection)
g_object_unref (info->added_connection);
if (!polkit_gnome_auth_obtain (pk_action, xid, pid, modify_connection_auth_cb, info, &err)) {
g_object_unref (info->exported);
g_free (info);
}
g_slice_free (ConnectionUpdateInfo, info);
}
static void
connection_update_remove_done (NMExportedConnection *exported,