Commit 071992a0 authored by Jonny Lamb's avatar Jonny Lamb

event-manager: become an approver for auth channels

Signed-off-by: Jonny Lamb's avatarJonny Lamb <jonnylamb@gnome.org>
parent d180fb24
......@@ -76,6 +76,7 @@ typedef struct {
typedef struct {
TpBaseClient *approver;
TpBaseClient *auth_approver;
EmpathyContactManager *contact_manager;
GSList *events;
/* Ongoing approvals */
......@@ -427,12 +428,47 @@ out:
g_object_unref (user_data);
}
static void
reject_auth_channel_claim_cb (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
TpChannelDispatchOperation *cdo = TP_CHANNEL_DISPATCH_OPERATION (source);
GError *error = NULL;
if (!tp_channel_dispatch_operation_claim_finish (cdo, result, &error))
{
DEBUG ("Failed to claim channel: %s", error->message);
g_error_free (error);
return;
}
tp_cli_channel_call_close (TP_CHANNEL (user_data), -1,
NULL, NULL, NULL, NULL);
}
static void
reject_approval (EventManagerApproval *approval)
{
/* We have to claim the channel before closing it */
tp_channel_dispatch_operation_claim_async (approval->operation,
reject_channel_claim_cb, g_object_ref (approval->handler_instance));
/* Unfortunately, we need to special case the auth channels for the
* time being as they don't have a wrapper object handler in
* approval->handler_instance as they're not actually handled by
* this process, so we can just use a noddy callback to call Close()
* directly. */
if (approval->handler_instance != NULL)
{
tp_channel_dispatch_operation_claim_async (approval->operation,
reject_channel_claim_cb, g_object_ref (approval->handler_instance));
}
else if (tp_channel_get_channel_type_id (approval->main_channel)
== TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_AUTHENTICATION)
{
tp_channel_dispatch_operation_claim_async (approval->operation,
reject_auth_channel_claim_cb, approval->main_channel);
}
}
static void
......@@ -828,8 +864,13 @@ event_manager_ft_got_contact_cb (TpConnection *connection,
g_object_unref (window);
}
/* If there is a file-transfer or media channel consider it as the
* main one. */
static void
dummy_process_func (EventPriv *event)
{
}
/* If there is a file-transfer, media, or auth channel consider it as
* the main one. */
static TpChannel *
find_main_channel (GList *channels)
{
......@@ -847,7 +888,8 @@ find_main_channel (GList *channels)
channel_type = tp_channel_get_channel_type_id (channel);
if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA ||
channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER)
channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER ||
channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_AUTHENTICATION)
return channel;
else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT)
......@@ -971,6 +1013,13 @@ approve_channels (TpSimpleApprover *approver,
empathy_tp_contact_factory_get_from_handle (connection, handle,
event_manager_ft_got_contact_cb, approval, NULL, G_OBJECT (self));
}
else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_AUTHENTICATION)
{
/* We need a process function or this will time out after
* NOTIFICATION_TIMEOUT seconds, which is undesirable. */
event_manager_add (approval->manager, account, NULL, EMPATHY_EVENT_TYPE_AUTH,
NULL, NULL, NULL, approval, dummy_process_func, NULL);
}
else
{
GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
......@@ -1159,6 +1208,7 @@ event_manager_finalize (GObject *object)
g_slist_free (priv->approvals);
g_object_unref (priv->contact_manager);
g_object_unref (priv->approver);
g_object_unref (priv->auth_approver);
g_object_unref (priv->gsettings_notif);
g_object_unref (priv->gsettings_ui);
g_object_unref (priv->sound_mgr);
......@@ -1200,7 +1250,6 @@ empathy_event_manager_class_init (EmpathyEventManagerClass *klass)
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1, G_TYPE_POINTER);
g_type_class_add_private (object_class, sizeof (EmpathyEventManagerPriv));
}
......@@ -1271,12 +1320,41 @@ empathy_event_manager_init (EmpathyEventManager *manager)
TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
NULL));
/* I don't feel good about doing this, and I'm sorry, but the
* capabilities connection feature is added earlier because it's
* needed for EmpathyTpChat. If the capabilities feature is required
* then preparing an auth channel (which of course appears in the
* CONNECTING state) will never be prepared. So the options are
* either to create another approver like I've done, or to port
* EmpathyTpChat and its users to not depend on the connection being
* prepared with capabilities. I chose the former, obviously. :-) */
priv->auth_approver = tp_simple_approver_new (dbus,
"Empathy.AuthEventManager", FALSE, approve_channels, manager,
NULL);
/* SASL auth channels */
tp_base_client_take_approver_filter (priv->auth_approver,
tp_asv_new (
TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
TP_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION,
TP_PROP_CHANNEL_TYPE_SERVER_AUTHENTICATION_AUTHENTICATION_METHOD,
G_TYPE_STRING,
TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
NULL));
if (!tp_base_client_register (priv->approver, &error))
{
DEBUG ("Failed to register Approver: %s", error->message);
g_error_free (error);
}
if (!tp_base_client_register (priv->auth_approver, &error))
{
DEBUG ("Failed to register auth Approver: %s", error->message);
g_error_free (error);
}
g_object_unref (dbus);
}
......
......@@ -55,6 +55,7 @@ typedef enum {
EMPATHY_EVENT_TYPE_SUBSCRIPTION,
EMPATHY_EVENT_TYPE_PRESENCE,
EMPATHY_EVENT_TYPE_INVITATION,
EMPATHY_EVENT_TYPE_AUTH,
} EmpathyEventType;
typedef struct {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment