diff options
author | Jonny Lamb <jonnylamb@gnome.org> | 2010-12-15 16:56:03 +0800 |
---|---|---|
committer | Jonny Lamb <jonnylamb@gnome.org> | 2010-12-15 16:56:03 +0800 |
commit | 2ec9b6e89141999f919f8a3bd4a44fd8abad86ff (patch) | |
tree | 10f81107c111564ec160d173db3b265a9573c4ff /libempathy | |
parent | 2e38a9c56cdac919f424107928dbbf35d69a41ed (diff) | |
parent | 225ca2e12b053a6c8ece18179d470f01ed1d6fb7 (diff) | |
download | gsoc2013-empathy-2ec9b6e89141999f919f8a3bd4a44fd8abad86ff.tar gsoc2013-empathy-2ec9b6e89141999f919f8a3bd4a44fd8abad86ff.tar.gz gsoc2013-empathy-2ec9b6e89141999f919f8a3bd4a44fd8abad86ff.tar.bz2 gsoc2013-empathy-2ec9b6e89141999f919f8a3bd4a44fd8abad86ff.tar.lz gsoc2013-empathy-2ec9b6e89141999f919f8a3bd4a44fd8abad86ff.tar.xz gsoc2013-empathy-2ec9b6e89141999f919f8a3bd4a44fd8abad86ff.tar.zst gsoc2013-empathy-2ec9b6e89141999f919f8a3bd4a44fd8abad86ff.zip |
Merge branch 'sasl-gui'
Diffstat (limited to 'libempathy')
-rw-r--r-- | libempathy/empathy-account-settings.c | 261 | ||||
-rw-r--r-- | libempathy/empathy-account-settings.h | 2 | ||||
-rw-r--r-- | libempathy/empathy-auth-factory.c | 280 | ||||
-rw-r--r-- | libempathy/empathy-auth-factory.h | 6 |
4 files changed, 470 insertions, 79 deletions
diff --git a/libempathy/empathy-account-settings.c b/libempathy/empathy-account-settings.c index e5191a96c..fe08f52c0 100644 --- a/libempathy/empathy-account-settings.c +++ b/libempathy/empathy-account-settings.c @@ -29,6 +29,7 @@ #include "empathy-account-settings.h" #include "empathy-connection-managers.h" +#include "empathy-keyring.h" #include "empathy-utils.h" #include "empathy-idle.h" @@ -49,6 +50,13 @@ enum { PROP_READY }; +enum { + PASSWORD_RETRIEVED = 1, + LAST_SIGNAL +}; + +static gulong signals[LAST_SIGNAL] = { 0, }; + /* private structure */ typedef struct _EmpathyAccountSettingsPriv EmpathyAccountSettingsPriv; @@ -59,6 +67,7 @@ struct _EmpathyAccountSettingsPriv TpAccountManager *account_manager; TpConnectionManager *manager; + TpProtocol *protocol_obj; TpAccount *account; gchar *cm_name; @@ -69,6 +78,15 @@ struct _EmpathyAccountSettingsPriv gboolean display_name_overridden; gboolean ready; + gboolean supports_sasl; + gboolean password_changed; + + gchar *password; + gchar *password_original; + + gboolean password_retrieved; + gboolean password_requested; + /* Parameter name (gchar *) -> parameter value (GValue) */ GHashTable *parameters; /* Keys are parameter names from the hash above (gchar *). @@ -80,6 +98,7 @@ struct _EmpathyAccountSettingsPriv GList *required_params; gulong managers_ready_id; + gboolean preparing_protocol; GSimpleAsyncResult *apply_result; }; @@ -226,8 +245,12 @@ empathy_account_settings_constructed (GObject *object) TP_ACCOUNT_FEATURE_STORAGE, 0 }; - tp_proxy_prepare_async (priv->account, features, - empathy_account_settings_account_ready_cb, self); + if (priv->account != NULL) + { + tp_proxy_prepare_async (priv->account, features, + empathy_account_settings_account_ready_cb, self); + } + tp_g_signal_connect_object (priv->managers, "notify::ready", G_CALLBACK (empathy_account_settings_managers_ready_cb), object, 0); } @@ -303,6 +326,13 @@ empathy_account_settings_class_init ( "Whether this account is ready to be used", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); + + signals[PASSWORD_RETRIEVED] = + g_signal_new ("password-retrieved", + G_TYPE_FROM_CLASS (empathy_account_settings_class), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void @@ -320,21 +350,11 @@ empathy_account_settings_dispose (GObject *object) g_signal_handler_disconnect (priv->managers, priv->managers_ready_id); priv->managers_ready_id = 0; - if (priv->managers != NULL) - g_object_unref (priv->managers); - priv->managers = NULL; - - if (priv->manager != NULL) - g_object_unref (priv->manager); - priv->manager = NULL; - - if (priv->account_manager != NULL) - g_object_unref (priv->account_manager); - priv->account_manager = NULL; - - if (priv->account != NULL) - g_object_unref (priv->account); - priv->account = NULL; + tp_clear_object (&priv->managers); + tp_clear_object (&priv->manager); + tp_clear_object (&priv->account_manager); + tp_clear_object (&priv->account); + tp_clear_object (&priv->protocol_obj); /* release any references held by the object here */ if (G_OBJECT_CLASS (empathy_account_settings_parent_class)->dispose) @@ -367,6 +387,8 @@ empathy_account_settings_finalize (GObject *object) g_free (priv->service); g_free (priv->display_name); g_free (priv->icon_name); + g_free (priv->password); + g_free (priv->password_original); if (priv->required_params != NULL) { @@ -385,10 +407,60 @@ empathy_account_settings_finalize (GObject *object) } static void +empathy_account_settings_protocol_obj_prepared_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + EmpathyAccountSettings *self = user_data; + GError *error = NULL; + + if (!tp_proxy_prepare_finish (source, result, &error)) + { + DEBUG ("Failed to prepare protocol object: %s", error->message); + g_clear_error (&error); + return; + } + + empathy_account_settings_check_readyness (self); +} + +static void +empathy_account_settings_get_password_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + EmpathyAccountSettings *self = user_data; + EmpathyAccountSettingsPriv *priv = GET_PRIV (self); + const gchar *password; + GError *error = NULL; + + password = empathy_keyring_get_password_finish (TP_ACCOUNT (source), + result, &error); + + if (error != NULL) + { + DEBUG ("Failed to get password: %s", error->message); + g_clear_error (&error); + } + + /* It doesn't really matter if getting the password failed; that + * just means that it's not there, or let's act like that at + * least. */ + + g_assert (priv->password == NULL); + + priv->password = g_strdup (password); + priv->password_original = g_strdup (password); + + g_signal_emit (self, signals[PASSWORD_RETRIEVED], 0); +} + +static void empathy_account_settings_check_readyness (EmpathyAccountSettings *self) { EmpathyAccountSettingsPriv *priv = GET_PRIV (self); const TpConnectionManagerProtocol *tp_protocol; + GQuark features[] = { TP_PROTOCOL_FEATURE_CORE, 0 }; if (priv->ready) return; @@ -400,12 +472,17 @@ empathy_account_settings_check_readyness (EmpathyAccountSettings *self) if (!empathy_connection_managers_is_ready (priv->managers)) return; - priv->manager = empathy_connection_managers_get_cm ( - priv->managers, priv->cm_name); + if (priv->manager == NULL) + { + priv->manager = empathy_connection_managers_get_cm ( + priv->managers, priv->cm_name); + } if (priv->manager == NULL) return; + g_object_ref (priv->manager); + if (priv->account != NULL) { g_free (priv->display_name); @@ -440,7 +517,43 @@ empathy_account_settings_check_readyness (EmpathyAccountSettings *self) } } - g_object_ref (priv->manager); + if (priv->protocol_obj == NULL) + { + priv->protocol_obj = g_object_ref ( + tp_connection_manager_get_protocol_object (priv->manager, + priv->protocol)); + } + + if (!tp_proxy_is_prepared (priv->protocol_obj, TP_PROTOCOL_FEATURE_CORE) + && !priv->preparing_protocol) + { + priv->preparing_protocol = TRUE; + tp_proxy_prepare_async (priv->protocol_obj, features, + empathy_account_settings_protocol_obj_prepared_cb, self); + return; + } + else + { + if (tp_strv_contains (tp_protocol_get_authentication_types ( + priv->protocol_obj), + TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION)) + { + priv->supports_sasl = TRUE; + } + } + + /* priv->account won't be a proper account if it's the account + * assistant showing this widget. */ + if (priv->supports_sasl && !priv->password_requested + && priv->account != NULL) + { + priv->password_requested = TRUE; + + /* Make this call but don't block on its readiness. We'll signal + * if it's updated later with ::password-retrieved. */ + empathy_keyring_get_password_async (priv->account, + empathy_account_settings_get_password_cb, self); + } priv->ready = TRUE; g_object_notify (G_OBJECT (self), "ready"); @@ -701,6 +814,14 @@ empathy_account_settings_unset (EmpathyAccountSettings *settings, if (empathy_account_settings_is_unset (settings, param)) return; + if (priv->supports_sasl && !tp_strdiff (param, "password")) + { + g_free (priv->password); + priv->password = NULL; + priv->password_changed = TRUE; + return; + } + v = g_strdup (param); g_array_append_val (priv->unset_parameters, v); @@ -714,14 +835,24 @@ empathy_account_settings_discard_changes (EmpathyAccountSettings *settings) g_hash_table_remove_all (priv->parameters); empathy_account_settings_free_unset_parameters (settings); + + priv->password_changed = FALSE; + g_free (priv->password); + priv->password = g_strdup (priv->password_original); } const gchar * empathy_account_settings_get_string (EmpathyAccountSettings *settings, const gchar *param) { + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); const GValue *v; + if (!tp_strdiff (param, "password") && priv->supports_sasl) + { + return priv->password; + } + v = empathy_account_settings_get (settings, param); if (v == NULL || !G_VALUE_HOLDS_STRING (v)) @@ -916,7 +1047,16 @@ empathy_account_settings_set_string (EmpathyAccountSettings *settings, g_return_if_fail (param != NULL); g_return_if_fail (value != NULL); - tp_asv_set_string (priv->parameters, g_strdup (param), value); + if (!tp_strdiff (param, "password") && priv->supports_sasl) + { + g_free (priv->password); + priv->password = g_strdup (value); + priv->password_changed = TRUE; + } + else + { + tp_asv_set_string (priv->parameters, g_strdup (param), value); + } account_settings_remove_from_unset (settings, param); } @@ -1152,6 +1292,55 @@ empathy_account_settings_set_icon_name_finish ( } static void +empathy_account_settings_processed_password (GObject *source, + GAsyncResult *result, + gpointer user_data, + gpointer finish_func) +{ + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (user_data); + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + GSimpleAsyncResult *r; + GError *error = NULL; + gboolean (*func) (TpAccount *source, GAsyncResult *result, GError **error) = + finish_func; + + g_free (priv->password_original); + priv->password_original = g_strdup (priv->password); + + if (!func (TP_ACCOUNT (source), result, &error)) + { + g_simple_async_result_set_from_error (priv->apply_result, error); + g_error_free (error); + } + + empathy_account_settings_discard_changes (settings); + + r = priv->apply_result; + priv->apply_result = NULL; + + g_simple_async_result_complete (r); + g_object_unref (r); +} + +static void +empathy_account_settings_set_password_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + empathy_account_settings_processed_password (source, result, user_data, + empathy_keyring_set_password_finish); +} + +static void +empathy_account_settings_delete_password_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + empathy_account_settings_processed_password (source, result, user_data, + empathy_keyring_delete_password_finish); +} + +static void empathy_account_settings_account_updated (GObject *source, GAsyncResult *result, gpointer user_data) @@ -1166,12 +1355,30 @@ empathy_account_settings_account_updated (GObject *source, { g_simple_async_result_set_from_error (priv->apply_result, error); g_error_free (error); + goto out; } - else + + /* Only set the password in the keyring if the CM supports SASL and + * it's changed. */ + if (priv->supports_sasl && priv->password_changed) { - empathy_account_settings_discard_changes (settings); + if (priv->password != NULL) + { + empathy_keyring_set_password_async (priv->account, priv->password, + empathy_account_settings_set_password_cb, settings); + } + else + { + empathy_keyring_delete_password_async (priv->account, + empathy_account_settings_delete_password_cb, settings); + } + + return; } +out: + empathy_account_settings_discard_changes (settings); + r = priv->apply_result; priv->apply_result = NULL; @@ -1451,3 +1658,11 @@ empathy_account_settings_get_tp_protocol (EmpathyAccountSettings *self) return tp_connection_manager_get_protocol (priv->manager, priv->protocol); } + +gboolean +empathy_account_settings_supports_sasl (EmpathyAccountSettings *self) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (self); + + return priv->supports_sasl; +} diff --git a/libempathy/empathy-account-settings.h b/libempathy/empathy-account-settings.h index 8f3634a19..4d5f6ddc9 100644 --- a/libempathy/empathy-account-settings.h +++ b/libempathy/empathy-account-settings.h @@ -189,6 +189,8 @@ gboolean empathy_account_settings_is_valid (EmpathyAccountSettings *settings); const TpConnectionManagerProtocol * empathy_account_settings_get_tp_protocol ( EmpathyAccountSettings *settings); +gboolean empathy_account_settings_supports_sasl (EmpathyAccountSettings *self); + G_END_DECLS #endif /* #ifndef __EMPATHY_ACCOUNT_SETTINGS_H__*/ diff --git a/libempathy/empathy-auth-factory.c b/libempathy/empathy-auth-factory.c index 578b6d6cd..443962a7c 100644 --- a/libempathy/empathy-auth-factory.c +++ b/libempathy/empathy-auth-factory.c @@ -26,17 +26,16 @@ #define DEBUG_FLAG EMPATHY_DEBUG_TLS #include "empathy-debug.h" +#include "empathy-keyring.h" #include "empathy-server-sasl-handler.h" #include "empathy-server-tls-handler.h" #include "empathy-utils.h" #include "extensions/extensions.h" -G_DEFINE_TYPE (EmpathyAuthFactory, empathy_auth_factory, G_TYPE_OBJECT); +G_DEFINE_TYPE (EmpathyAuthFactory, empathy_auth_factory, TP_TYPE_BASE_CLIENT); typedef struct { - TpBaseClient *handler; - /* Keep a ref here so the auth client doesn't have to mess with * refs. It will be cleared when the channel (and so the handler) * gets invalidated. */ @@ -79,7 +78,9 @@ handler_context_data_new (EmpathyAuthFactory *self, data = g_slice_new0 (HandlerContextData); data->self = g_object_ref (self); - data->context = g_object_ref (context); + + if (context != NULL) + data->context = g_object_ref (context); return data; } @@ -145,13 +146,16 @@ server_sasl_handler_ready_cb (GObject *source, { DEBUG ("Failed to create a server SASL handler; error %s", error->message); - tp_handle_channels_context_fail (data->context, error); + + if (data->context != NULL) + tp_handle_channels_context_fail (data->context, error); g_error_free (error); } else { - tp_handle_channels_context_accept (data->context); + if (data->context != NULL) + tp_handle_channels_context_accept (data->context); g_signal_connect (priv->sasl_handler, "invalidated", G_CALLBACK (sasl_handler_invalidated_cb), data->self); @@ -163,26 +167,17 @@ server_sasl_handler_ready_cb (GObject *source, handler_context_data_free (data); } -static void -handle_channels_cb (TpSimpleHandler *handler, - TpAccount *account, - TpConnection *connection, +static gboolean +common_checks (EmpathyAuthFactory *self, GList *channels, - GList *requests_satisfied, - gint64 user_action_time, - TpHandleChannelsContext *context, - gpointer user_data) + gboolean must_be_sasl, + GError **error) { - TpChannel *channel; - const GError *dbus_error; - GError *error = NULL; - EmpathyAuthFactory *self = user_data; EmpathyAuthFactoryPriv *priv = GET_PRIV (self); - HandlerContextData *data; + TpChannel *channel; GHashTable *props; const gchar * const *available_mechanisms; - - DEBUG ("Handle TLS or SASL carrier channels."); + const GError *dbus_error; /* there can't be more than one ServerTLSConnection or * ServerAuthentication channels at the same time, for the same @@ -190,35 +185,38 @@ handle_channels_cb (TpSimpleHandler *handler, */ if (g_list_length (channels) != 1) { - g_set_error_literal (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + g_set_error_literal (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Can't handle more than one ServerTLSConnection or ServerAuthentication " "channel for the same connection."); - goto error; + return FALSE; } channel = channels->data; if (tp_channel_get_channel_type_id (channel) != - EMP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION - && tp_channel_get_channel_type_id (channel) != TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_AUTHENTICATION) { - g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, - "Can only handle ServerTLSConnection or ServerAuthentication channels, " - "this was a %s channel", tp_channel_get_channel_type (channel)); - - goto error; + if (must_be_sasl + || tp_channel_get_channel_type_id (channel) != + EMP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION) + { + g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + "Can only handle ServerTLSConnection or ServerAuthentication channels, " + "this was a %s channel", tp_channel_get_channel_type (channel)); + + return FALSE; + } } if (tp_channel_get_channel_type_id (channel) == TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_AUTHENTICATION && priv->sasl_handler != NULL) { - g_set_error_literal (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + g_set_error_literal (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Can't handle more than one ServerAuthentication channel at one time"); - goto error; + return FALSE; } props = tp_channel_borrow_immutable_properties (channel); @@ -230,20 +228,50 @@ handle_channels_cb (TpSimpleHandler *handler, TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_AUTHENTICATION && !tp_strv_contains (available_mechanisms, "X-TELEPATHY-PASSWORD")) { - g_set_error_literal (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + g_set_error_literal (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Only the X-TELEPATHY-PASSWORD SASL mechanism is supported"); - goto error; + return FALSE; } dbus_error = tp_proxy_get_invalidated (channel); if (dbus_error != NULL) { - error = g_error_copy (dbus_error); - goto error; + *error = g_error_copy (dbus_error); + return FALSE; + } + + return TRUE; +} + +static void +handle_channels (TpBaseClient *handler, + TpAccount *account, + TpConnection *connection, + GList *channels, + GList *requests_satisfied, + gint64 user_action_time, + TpHandleChannelsContext *context) +{ + TpChannel *channel; + GError *error = NULL; + EmpathyAuthFactory *self = EMPATHY_AUTH_FACTORY (handler); + HandlerContextData *data; + + DEBUG ("Handle TLS or SASL carrier channels."); + + if (!common_checks (self, channels, FALSE, &error)) + { + DEBUG ("Failed checks: %s", error->message); + tp_handle_channels_context_fail (context, error); + g_clear_error (&error); + return; } + /* The common checks above have checked this is fine. */ + channel = channels->data; + data = handler_context_data_new (self, context); tp_handle_channels_context_delay (context); @@ -260,11 +288,125 @@ handle_channels_cb (TpSimpleHandler *handler, empathy_server_sasl_handler_new_async (account, channel, server_sasl_handler_ready_cb, data); } - return; +} - error: - tp_handle_channels_context_fail (context, error); - g_clear_error (&error); +typedef struct +{ + EmpathyAuthFactory *self; + TpObserveChannelsContext *context; + TpChannelDispatchOperation *dispatch_operation; + TpAccount *account; + TpChannel *channel; +} ObserveChannelsData; + +static void +observe_channels_data_free (ObserveChannelsData *data) +{ + g_object_unref (data->context); + g_object_unref (data->account); + g_object_unref (data->channel); + g_object_unref (data->dispatch_operation); + g_slice_free (ObserveChannelsData, data); +} + +static void +claim_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + ObserveChannelsData *data = user_data; + GError *error = NULL; + + if (!tp_channel_dispatch_operation_claim_finish ( + TP_CHANNEL_DISPATCH_OPERATION (source), result, &error)) + { + DEBUG ("Failed to call Claim: %s", error->message); + g_clear_error (&error); + } + else + { + HandlerContextData *h_data; + + DEBUG ("Claim called successfully"); + + h_data = handler_context_data_new (data->self, NULL); + + empathy_server_sasl_handler_new_async (TP_ACCOUNT (data->account), + data->channel, server_sasl_handler_ready_cb, h_data); + } + + observe_channels_data_free (data); +} + +static void +get_password_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + ObserveChannelsData *data = user_data; + + if (empathy_keyring_get_password_finish (TP_ACCOUNT (source), result, NULL) == NULL) + { + /* We don't actually mind if this fails, just let the approver + * go ahead and take the channel. */ + + DEBUG ("We don't have a password for account %s, letting the event " + "manager approver take it", tp_proxy_get_object_path (source)); + + tp_observe_channels_context_accept (data->context); + observe_channels_data_free (data); + } + else + { + DEBUG ("We have a password for account %s, calling Claim", + tp_proxy_get_object_path (source)); + + tp_channel_dispatch_operation_claim_async (data->dispatch_operation, + claim_cb, data); + + tp_observe_channels_context_accept (data->context); + } +} + +static void +observe_channels (TpBaseClient *client, + TpAccount *account, + TpConnection *connection, + GList *channels, + TpChannelDispatchOperation *dispatch_operation, + GList *requests, + TpObserveChannelsContext *context) +{ + EmpathyAuthFactory *self = EMPATHY_AUTH_FACTORY (client); + TpChannel *channel; + GError *error = NULL; + ObserveChannelsData *data; + + DEBUG ("New auth channel to observe"); + + if (!common_checks (self, channels, TRUE, &error)) + { + DEBUG ("Failed checks: %s", error->message); + tp_observe_channels_context_fail (context, error); + g_clear_error (&error); + return; + } + + /* We're now sure this is a server auth channel using the SASL auth + * type and X-TELEPATHY-PASSWORD is available. Great. */ + + channel = channels->data; + + data = g_slice_new0 (ObserveChannelsData); + data->self = self; + data->context = g_object_ref (context); + data->dispatch_operation = g_object_ref (dispatch_operation); + data->account = g_object_ref (account); + data->channel = g_object_ref (channel); + + empathy_keyring_get_password_async (account, get_password_cb, data); + + tp_observe_channels_context_delay (context); } static GObject * @@ -293,14 +435,20 @@ empathy_auth_factory_constructor (GType type, static void empathy_auth_factory_init (EmpathyAuthFactory *self) { - EmpathyAuthFactoryPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, EMPATHY_TYPE_AUTH_FACTORY, EmpathyAuthFactoryPriv); - TpDBusDaemon *bus; +} + +static void +empathy_auth_factory_constructed (GObject *obj) +{ + EmpathyAuthFactory *self = EMPATHY_AUTH_FACTORY (obj); + TpBaseClient *client = TP_BASE_CLIENT (self); GError *error = NULL; - self->priv = priv; + /* chain up to TpBaseClient first */ + G_OBJECT_CLASS (empathy_auth_factory_parent_class)->constructed (obj); - bus = tp_dbus_daemon_dup (&error); if (error != NULL) { g_critical ("Failed to get TpDBusDaemon: %s", error->message); @@ -308,10 +456,9 @@ empathy_auth_factory_init (EmpathyAuthFactory *self) return; } - priv->handler = tp_simple_handler_new (bus, FALSE, FALSE, "Empathy.Auth", - FALSE, handle_channels_cb, self, NULL); + tp_base_client_set_handler_bypass_approval (client, FALSE); - tp_base_client_take_handler_filter (priv->handler, tp_asv_new ( + tp_base_client_take_handler_filter (client, tp_asv_new ( /* ChannelType */ TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, EMP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, @@ -319,7 +466,7 @@ empathy_auth_factory_init (EmpathyAuthFactory *self) TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_NONE, NULL)); - tp_base_client_take_handler_filter (priv->handler, tp_asv_new ( + tp_base_client_take_handler_filter (client, tp_asv_new ( /* ChannelType */ TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION, @@ -328,7 +475,20 @@ empathy_auth_factory_init (EmpathyAuthFactory *self) G_TYPE_STRING, TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION, NULL)); - g_object_unref (bus); + /* We are also an observer so that we can see new auth channels + * popping up and if we have the password already saved to one + * account where an auth channel has just appeared we can call + * Claim() on the CDO so the approver won't get it, which makes + * sense. */ + + tp_base_client_take_observer_filter (client, tp_asv_new ( + /* ChannelType */ + TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, + TP_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION, + /* AuthenticationMethod */ + TP_PROP_CHANNEL_TYPE_SERVER_AUTHENTICATION_AUTHENTICATION_METHOD, + G_TYPE_STRING, TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION, + NULL)); } static void @@ -341,7 +501,6 @@ empathy_auth_factory_dispose (GObject *object) priv->dispose_run = TRUE; - tp_clear_object (&priv->handler); tp_clear_object (&priv->sasl_handler); G_OBJECT_CLASS (empathy_auth_factory_parent_class)->dispose (object); @@ -351,10 +510,15 @@ static void empathy_auth_factory_class_init (EmpathyAuthFactoryClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); + TpBaseClientClass *base_client_cls = TP_BASE_CLIENT_CLASS (klass); oclass->constructor = empathy_auth_factory_constructor; + oclass->constructed = empathy_auth_factory_constructed; oclass->dispose = empathy_auth_factory_dispose; + base_client_cls->handle_channels = handle_channels; + base_client_cls->observe_channels = observe_channels; + g_type_class_add_private (klass, sizeof (EmpathyAuthFactoryPriv)); signals[NEW_SERVER_TLS_HANDLER] = @@ -379,14 +543,22 @@ empathy_auth_factory_class_init (EmpathyAuthFactoryClass *klass) EmpathyAuthFactory * empathy_auth_factory_dup_singleton (void) { - return g_object_new (EMPATHY_TYPE_AUTH_FACTORY, NULL); + EmpathyAuthFactory *out = NULL; + TpDBusDaemon *bus; + + bus = tp_dbus_daemon_dup (NULL); + out = g_object_new (EMPATHY_TYPE_AUTH_FACTORY, + "dbus-daemon", bus, + "name", "Empathy.Auth", + NULL); + g_object_unref (bus); + + return out; } gboolean empathy_auth_factory_register (EmpathyAuthFactory *self, GError **error) { - EmpathyAuthFactoryPriv *priv = GET_PRIV (self); - - return tp_base_client_register (priv->handler, error); + return tp_base_client_register (TP_BASE_CLIENT (self), error); } diff --git a/libempathy/empathy-auth-factory.h b/libempathy/empathy-auth-factory.h index 507f69b95..6f62a7a86 100644 --- a/libempathy/empathy-auth-factory.h +++ b/libempathy/empathy-auth-factory.h @@ -23,17 +23,19 @@ #include <glib-object.h> +#include <telepathy-glib/base-client.h> + G_BEGIN_DECLS typedef struct _EmpathyAuthFactory EmpathyAuthFactory; typedef struct _EmpathyAuthFactoryClass EmpathyAuthFactoryClass; struct _EmpathyAuthFactoryClass { - GObjectClass parent_class; + TpBaseClientClass parent_class; }; struct _EmpathyAuthFactory { - GObject parent; + TpBaseClient parent; gpointer priv; }; |