Commit 6878f634 authored by Dan Williams's avatar Dan Williams
Browse files

editor: fix secrets requests after 78b7101d

After 78b7101d, the page's connection
would of course be the duplicated connection which is a plain
NMConnection that user edits are done on.  THat of course doesn't
implement NMSettingsConnectionInterface, and thus can't respond to
requests for secrets.

Instead, we have the CEPage subclasses for each setting type pass back
the name of the setting they want secrets for, if they need secrets,
and let the editor ask for the secrets since it has the original
connection which usually implements NMSettingsConnectionInterface.

By moving the addition of the page's GtkWidget to after page
initialization, we also fix system VPN connections, which were broken
because the VPN page's plugin-provided widget is only valid after
the page is initialized, but the editor expected it to be valid
right after requesting secrets.  In the case of system secrets, the
request is over D-Bus and is async, which meant that the call would
complete and the page would initalize long after the connection editor
had tried to add the page to the UI.
parent a92794e1
......@@ -175,34 +175,40 @@ emit_initialized (CEPage *self, GError *error)
g_signal_emit (self, signals[INITIALIZED], 0, NULL, error);
}
static void
get_secrets_cb (NMSettingsConnectionInterface *connection,
void
ce_page_complete_init (CEPage *self,
const char *setting_name,
GHashTable *secrets,
GError *error,
gpointer user_data)
GError *error)
{
CEPage *self = user_data;
GError *update_error = NULL;
GHashTable *setting_hash;
g_return_if_fail (self != NULL);
g_return_if_fail (CE_IS_PAGE (self));
if (error) {
emit_initialized (self, error);
return;
} else if (!setting_name || !secrets) {
/* Success, no secrets */
emit_initialized (self, NULL);
return;
}
g_assert (setting_name);
g_assert (secrets);
/* Update the connection with the new secrets */
setting_hash = g_hash_table_lookup (secrets, self->setting_name);
/* No secrets? */
setting_hash = g_hash_table_lookup (secrets, setting_name);
if (!setting_hash) {
/* Success, no secrets */
emit_initialized (self, NULL);
return;
}
if (nm_connection_update_secrets (self->connection,
self->setting_name,
setting_name,
setting_hash,
&update_error)) {
/* Success */
......@@ -219,40 +225,6 @@ get_secrets_cb (NMSettingsConnectionInterface *connection,
g_clear_error (&update_error);
}
gboolean
ce_page_initialize (CEPage *self,
const char *setting_name,
GError **error)
{
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (self->connection != NULL, FALSE);
/* Don't need to request secrets for settings which are known not to have any */
if (!setting_name) {
emit_initialized (self, NULL);
return TRUE;
}
/* Don't request secrets from a plain NMConnection either, since we only
* use those during add/import where the secrets are already filled in.
*/
if (!NM_IS_SETTINGS_CONNECTION_INTERFACE (self->connection)) {
emit_initialized (self, NULL);
return TRUE;
}
if (self->setting_name)
g_free (self->setting_name);
self->setting_name = g_strdup (setting_name);
return nm_settings_connection_interface_get_secrets (NM_SETTINGS_CONNECTION_INTERFACE (self->connection),
self->setting_name,
NULL,
FALSE,
get_secrets_cb,
self);
}
static void
ce_page_init (CEPage *self)
{
......@@ -289,7 +261,6 @@ finalize (GObject *object)
CEPage *self = CE_PAGE (object);
g_free (self->title);
g_free (self->setting_name);
G_OBJECT_CLASS (ce_page_parent_class)->finalize (object);
}
......
......@@ -66,7 +66,6 @@ typedef struct {
DBusGProxy *proxy;
gulong secrets_done_validate;
char *setting_name;
NMConnection *connection;
GtkWindow *parent_window;
......@@ -85,7 +84,10 @@ typedef struct {
} CEPageClass;
typedef CEPage* (*CEPageNewFunc)(NMConnection *connection, GtkWindow *parent, GError **error);
typedef CEPage* (*CEPageNewFunc)(NMConnection *connection,
GtkWindow *parent,
const char **out_secrets_setting_name,
GError **error);
GType ce_page_get_type (void);
......@@ -106,9 +108,10 @@ gint ce_spin_output_with_default (GtkSpinButton *spin, gpointer user_data);
int ce_get_property_default (NMSetting *setting, const char *property_name);
gboolean ce_page_initialize (CEPage *self,
void ce_page_complete_init (CEPage *self,
const char *setting_name,
GError **error);
GHashTable *secrets,
GError *error);
gboolean ce_page_get_initialized (CEPage *self);
......
......@@ -511,16 +511,94 @@ static void
page_initialized (CEPage *page, gpointer unused, GError *error, gpointer user_data)
{
NMConnectionEditor *editor = NM_CONNECTION_EDITOR (user_data);
GtkWidget *widget;
GtkWidget *notebook;
GtkWidget *label;
if (error) {
g_object_unref (page);
gtk_widget_hide (editor->window);
g_signal_emit (editor, editor_signals[EDITOR_DONE], 0, GTK_RESPONSE_NONE, error);
return;
}
/* Add the page to the UI */
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);
editor->pages = g_slist_append (editor->pages, page);
recheck_initialization (editor);
}
typedef struct {
NMConnectionEditor *self;
CEPage *page;
char *setting_name;
} GetSecretsInfo;
static void
get_secrets_cb (NMSettingsConnectionInterface *connection,
GHashTable *secrets,
GError *error,
gpointer user_data)
{
GetSecretsInfo *info = user_data;
ce_page_complete_init (info->page, info->setting_name, secrets, error);
g_free (info->setting_name);
g_free (info);
}
static void
get_secrets_for_page (NMConnectionEditor *self,
CEPage *page,
const char *setting_name)
{
GetSecretsInfo *info;
gboolean success = FALSE;
if (!setting_name) {
/* page doesn't need any secrets */
ce_page_complete_init (page, NULL, NULL, NULL);
return;
}
/* Try to get secrets from ->orig_connection, because it's the one that
* implements NMSettingsConnectionInterface and can respond to requests for
* its secrets. ->connection is a plain NMConnection copy of ->orig_connection
* which is the connection that's actually changed when the user clicks stuff.
* When creating importing or creating new connections though, ->orig_connection
* is an NMConnection because it hasn't been exported over D-Bus yet, so we
* can't ask it for secrets, because it doesn't implement NMSettingsConnectionInterface.
*/
if (!NM_IS_SETTINGS_CONNECTION_INTERFACE (self->orig_connection)) {
ce_page_complete_init (page, setting_name, NULL, NULL);
return;
}
info = g_malloc0 (sizeof (GetSecretsInfo));
info->self = self;
info->page = page;
info->setting_name = g_strdup (setting_name);
success = nm_settings_connection_interface_get_secrets (NM_SETTINGS_CONNECTION_INTERFACE (self->orig_connection),
setting_name,
NULL,
FALSE,
get_secrets_cb,
info);
if (!success) {
GError *error;
error = g_error_new_literal (0, 0, _("Failed to update connection secrets due to an unknown error."));
get_secrets_cb (NM_SETTINGS_CONNECTION_INTERFACE (self->orig_connection), NULL, error, info);
g_error_free (error);
}
}
static gboolean
add_page (NMConnectionEditor *editor,
CEPageNewFunc func,
......@@ -528,28 +606,24 @@ add_page (NMConnectionEditor *editor,
GError **error)
{
CEPage *page;
GtkWidget *widget;
GtkWidget *notebook;
GtkWidget *label;
const char *secrets_setting_name = 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);
page = (*func) (connection, GTK_WINDOW (editor->window), &secrets_setting_name, 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);
editor->pages = g_slist_append (editor->pages, page);
g_signal_connect (page, "changed", G_CALLBACK (page_changed), editor);
g_signal_connect (page, "initialized", G_CALLBACK (page_initialized), editor);
/* Request any secrets the page might require; or if it doesn't want any,
* let the page initialize.
*/
get_secrets_for_page (editor, page, secrets_setting_name);
return TRUE;
}
......
......@@ -120,7 +120,10 @@ finish_setup (CEPageDsl *self, gpointer unused, GError *error, gpointer user_dat
}
CEPage *
ce_page_dsl_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
ce_page_dsl_new (NMConnection *connection,
GtkWindow *parent_window,
const char **out_secrets_setting_name,
GError **error)
{
CEPageDsl *self;
CEPageDslPrivate *priv;
......@@ -159,10 +162,8 @@ ce_page_dsl_new (NMConnection *connection, GtkWindow *parent_window, GError **er
}
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;
}
*out_secrets_setting_name = NM_SETTING_PPPOE_SETTING_NAME;
return CE_PAGE (self);
}
......
......@@ -47,7 +47,10 @@ typedef struct {
GType ce_page_dsl_get_type (void);
CEPage *ce_page_dsl_new (NMConnection *connection, GtkWindow *parent, GError **error);
CEPage *ce_page_dsl_new (NMConnection *connection,
GtkWindow *parent,
const char **out_secrets_setting_name,
GError **error);
void dsl_connection_new (GtkWindow *parent,
PageNewConnectionResultFunc callback,
......
......@@ -690,7 +690,10 @@ finish_setup (CEPageIP4 *self, gpointer unused, GError *error, gpointer user_dat
}
CEPage *
ce_page_ip4_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
ce_page_ip4_new (NMConnection *connection,
GtkWindow *parent_window,
const char **out_secrets_setting_name,
GError **error)
{
CEPageIP4 *self;
CEPageIP4Private *priv;
......@@ -736,10 +739,6 @@ ce_page_ip4_new (NMConnection *connection, GtkWindow *parent_window, GError **er
}
g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
if (!ce_page_initialize (parent, NULL, error)) {
g_object_unref (self);
return NULL;
}
return CE_PAGE (self);
}
......
......@@ -47,7 +47,10 @@ typedef struct {
GType ce_page_ip4_get_type (void);
CEPage *ce_page_ip4_new (NMConnection *connection, GtkWindow *parent, GError **error);
CEPage *ce_page_ip4_new (NMConnection *connection,
GtkWindow *parent,
const char **out_secrets_setting_name,
GError **error);
#endif /* __PAGE_IP4_H__ */
......@@ -649,7 +649,10 @@ finish_setup (CEPageIP6 *self, gpointer unused, GError *error, gpointer user_dat
}
CEPage *
ce_page_ip6_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
ce_page_ip6_new (NMConnection *connection,
GtkWindow *parent_window,
const char **out_secrets_setting_name,
GError **error)
{
CEPageIP6 *self;
CEPageIP6Private *priv;
......@@ -695,10 +698,6 @@ ce_page_ip6_new (NMConnection *connection, GtkWindow *parent_window, GError **er
}
g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
if (!ce_page_initialize (parent, NULL, error)) {
g_object_unref (self);
return NULL;
}
return CE_PAGE (self);
}
......
......@@ -47,7 +47,10 @@ typedef struct {
GType ce_page_ip6_get_type (void);
CEPage *ce_page_ip6_new (NMConnection *connection, GtkWindow *parent, GError **error);
CEPage *ce_page_ip6_new (NMConnection *connection,
GtkWindow *parent,
const char **out_secrets_setting_name,
GError **error);
#endif /* __PAGE_IP6_H__ */
......@@ -293,12 +293,14 @@ finish_setup (CEPageMobile *self, gpointer unused, GError *error, gpointer user_
}
CEPage *
ce_page_mobile_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
ce_page_mobile_new (NMConnection *connection,
GtkWindow *parent_window,
const char **out_secrets_setting_name,
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,
CE_PAGE_CONNECTION, connection,
......@@ -327,9 +329,12 @@ ce_page_mobile_new (NMConnection *connection, GtkWindow *parent_window, GError *
priv = CE_PAGE_MOBILE_GET_PRIVATE (self);
priv->setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM);
if (!priv->setting) {
if (priv->setting)
*out_secrets_setting_name = NM_SETTING_GSM_SETTING_NAME;
else {
priv->setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA);
setting_name = NM_SETTING_CDMA_SETTING_NAME;
if (priv->setting)
*out_secrets_setting_name = NM_SETTING_CDMA_SETTING_NAME;
}
if (!priv->setting) {
......@@ -339,10 +344,6 @@ ce_page_mobile_new (NMConnection *connection, GtkWindow *parent_window, GError *
}
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 CE_PAGE (self);
}
......
......@@ -47,7 +47,10 @@ typedef struct {
GType ce_page_mobile_get_type (void);
CEPage *ce_page_mobile_new (NMConnection *connection, GtkWindow *parent, GError **error);
CEPage *ce_page_mobile_new (NMConnection *connection,
GtkWindow *parent,
const char **out_secrets_setting_name,
GError **error);
void mobile_connection_new (GtkWindow *parent,
PageNewConnectionResultFunc result_func,
......
......@@ -262,7 +262,10 @@ finish_setup (CEPagePpp *self, gpointer unused, GError *error, gpointer user_dat
}
CEPage *
ce_page_ppp_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
ce_page_ppp_new (NMConnection *connection,
GtkWindow *parent_window,
const char **out_secrets_setting_name,
GError **error)
{
CEPagePpp *self;
CEPagePppPrivate *priv;
......@@ -308,10 +311,8 @@ ce_page_ppp_new (NMConnection *connection, GtkWindow *parent_window, GError **er
priv->connection_id = g_strdup (nm_setting_connection_get_id (s_con));
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;
}
*out_secrets_setting_name = NM_SETTING_PPP_SETTING_NAME;
return CE_PAGE (self);
}
......
......@@ -47,6 +47,9 @@ typedef struct {
GType ce_page_ppp_get_type (void);
CEPage *ce_page_ppp_new (NMConnection *connection, GtkWindow *parent, GError **error);
CEPage *ce_page_ppp_new (NMConnection *connection,
GtkWindow *parent,
const char **out_secrets_setting_name,
GError **error);
#endif /* __PAGE_PPP_H__ */
......@@ -88,7 +88,10 @@ finish_setup (CEPageVpn *self, gpointer unused, GError *error, gpointer user_dat
}
CEPage *
ce_page_vpn_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
ce_page_vpn_new (NMConnection *connection,
GtkWindow *parent_window,
const char **out_secrets_setting_name,
GError **error)
{
CEPageVpn *self;
CEPageVpnPrivate *priv;
......@@ -119,10 +122,8 @@ ce_page_vpn_new (NMConnection *connection, GtkWindow *parent_window, GError **er
}
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;
}
*out_secrets_setting_name = NM_SETTING_VPN_SETTING_NAME;
return CE_PAGE (self);
}
......
......@@ -47,7 +47,10 @@ typedef struct {
GType ce_page_vpn_get_type (void);
CEPage *ce_page_vpn_new (NMConnection *connection, GtkWindow *parent, GError **error);
CEPage *ce_page_vpn_new (NMConnection *connection,
GtkWindow *parent,
const char **out_secrets_setting_name,
GError **error);
gboolean ce_page_vpn_save_secrets (CEPage *page, NMConnection *connection);
......
......@@ -96,7 +96,10 @@ finish_setup (CEPageWiredSecurity *self, gpointer unused, GError *error, gpointe
}
CEPage *
ce_page_wired_security_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
ce_page_wired_security_new (NMConnection *connection,
GtkWindow *parent_window,
const char **out_secrets_setting_name,
GError **error)
{
CEPageWiredSecurity *self;
CEPage *parent;
......@@ -120,12 +123,9 @@ ce_page_wired_security_new (NMConnection *connection, GtkWindow *parent_window,
priv->enabled = GTK_TOGGLE_BUTTON (gtk_check_button_new_with_label (_("Use 802.1X security for this connection")));
g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
if (!ce_page_initialize (parent,
priv->initial_have_8021x ? NM_SETTING_802_1X_SETTING_NAME : NULL,
error)) {
g_object_unref (self);
return NULL;
}
if (priv->initial_have_8021x)
*out_secrets_setting_name = NM_SETTING_802_1X_SETTING_NAME;
return CE_PAGE (self);
}
......
......@@ -49,6 +49,9 @@ typedef struct {
GType ce_page_wired_security_get_type (void);
CEPage *ce_page_wired_security_new (NMConnection *connection, GtkWindow *parent, GError **error);
CEPage *ce_page_wired_security_new (NMConnection *connection,
GtkWindow *parent,
const char **out_secrets_setting_name,
GError **error);
#endif /* __PAGE_WIRED_SECURITY_H__ */
......@@ -187,7 +187,10 @@ finish_setup (CEPageWired *self, gpointer unused, GError *error, gpointer user_d
}
CEPage *
ce_page_wired_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
ce_page_wired_new (NMConnection *connection,
GtkWindow *parent_window,
const char **out_secrets_setting_name,
GError **error)
{
CEPageWired *self;
CEPageWiredPrivate *priv;
......@@ -226,10 +229,6 @@ ce_page_wired_new (NMConnection *connection, GtkWindow *parent_window, GError **
}
g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
if (!ce_page_initialize (parent, NULL, error)) {
g_object_unref (self);
return NULL;
}
return CE_PAGE (self);
}
......
......@@ -47,7 +47,10 @@ typedef struct {
GType ce_page_wired_get_type (void);
CEPage *ce_page_wired_new (NMConnection *connection, GtkWindow *parent, GError **error);
CEPage *ce_page_wired_new (NMConnection *connection,
GtkWindow *parent,
const char **out_secrets_setting_name,
GError **error);
void wired_connection_new (GtkWindow *parent,
PageNewConnectionResultFunc result_func,
......
......@@ -342,13 +342,15 @@ finish_setup (CEPageWirelessSecurity *self, gpointer unused, GError *error, gpoi
}
CEPage *
ce_page_wireless_security_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
ce_page_wireless_security_new (NMConnection *connection,
GtkWindow *parent_window,
const char **out_secrets_setting_name,
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;
......@@ -398,21 +400,17 @@ ce_page_wireless_security_new (NMConnection *connection, GtkWindow *parent_windo
|| 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;
*out_secrets_setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;