From a3edc0a95cc36a344d1062c34683a3fa7eea43d9 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 5 Oct 2012 12:04:02 +0100 Subject: [PATCH 2/8] McdAccount: take responsibility for setting the nickname As well as being implemented in a more streamlined way (using the self-contact instead of calling D-Bus methods directly), this reduces the circular dependencies between McdConnection and McdAccount. --- src/mcd-account.c | 125 ++++++++++++++++++++++++++++++++------ src/mcd-connection-priv.h | 3 - src/mcd-connection.c | 147 --------------------------------------------- 3 files changed, 107 insertions(+), 168 deletions(-) diff --git a/src/mcd-account.c b/src/mcd-account.c index 60d5c7a..2d51165 100644 --- a/src/mcd-account.c +++ b/src/mcd-account.c @@ -1312,6 +1312,44 @@ get_service (TpSvcDBusProperties *self, const gchar *name, GValue *value) mcd_account_get_string_val (account, name, value); } +static void +mcd_account_set_self_alias_cb (TpConnection *tp_connection, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + if (error) + WARNING ("%s", error->message); +} + +static void +mcd_account_send_nickname_to_connection (McdAccount *self, + const gchar *nickname) +{ + if (self->priv->tp_connection == NULL) + return; + + if (self->priv->self_contact == NULL) + return; + + DEBUG ("%s: '%s'", self->priv->unique_name, nickname); + + if (tp_proxy_has_interface_by_id (self->priv->tp_connection, + TP_IFACE_QUARK_CONNECTION_INTERFACE_ALIASING)) + { + GHashTable *aliases = g_hash_table_new (NULL, NULL); + + g_hash_table_insert (aliases, + GUINT_TO_POINTER (tp_contact_get_handle (self->priv->self_contact)), + (gchar *) nickname); + tp_cli_connection_interface_aliasing_call_set_aliases ( + self->priv->tp_connection, -1, aliases, + mcd_account_set_self_alias_cb, NULL, NULL, NULL); + g_hash_table_unref (aliases); + } +} + + static gboolean set_nickname (TpSvcDBusProperties *self, const gchar *name, const GValue *value, GError **error) @@ -1323,14 +1361,10 @@ set_nickname (TpSvcDBusProperties *self, const gchar *name, DEBUG ("called for %s", priv->unique_name); ret = mcd_account_set_string_val (account, name, value, error); - /* we need to call _mcd_connection_set_nickname for side effects, * - * as that is how the CM is informed of the current nickname, even * - * if the nickname hasn't changed from our POV */ - if (priv->connection != NULL) + if (ret != SET_RESULT_ERROR) { - /* this is a no-op if the connection doesn't support it */ - _mcd_connection_set_nickname (priv->connection, - g_value_get_string (value)); + mcd_account_send_nickname_to_connection (account, + g_value_get_string (value)); } return (ret != SET_RESULT_ERROR); @@ -4021,15 +4055,18 @@ _mcd_account_get_supersedes (McdAccount *self) } static void -mcd_account_connection_self_nickname_changed_cb (McdAccount *account, - const gchar *alias, - McdConnection *connection) +mcd_account_self_contact_notify_alias_cb (McdAccount *self, + GParamSpec *unused_param_spec G_GNUC_UNUSED, + TpContact *self_contact) { GValue value = G_VALUE_INIT; + if (self_contact != self->priv->self_contact) + return; + g_value_init (&value, G_TYPE_STRING); - g_value_set_static_string (&value, alias); - mcd_account_set_string_val (account, MC_ACCOUNTS_KEY_ALIAS, &value, NULL); + g_object_get_property (G_OBJECT (self_contact), "alias", &value); + mcd_account_set_string_val (self, MC_ACCOUNTS_KEY_ALIAS, &value, NULL); g_value_unset (&value); } @@ -4485,9 +4522,60 @@ _mcd_account_get_old_avatar_filename (McdAccount *account, } static void +mcd_account_self_contact_upgraded_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + McdAccount *self = tp_weak_ref_dup_object (user_data); + GPtrArray *contacts = NULL; + GError *error = NULL; + + if (self == NULL) + return; + + g_return_if_fail (MCD_IS_ACCOUNT (self)); + + if (tp_connection_upgrade_contacts_finish (TP_CONNECTION (source_object), + res, &contacts, &error)) + { + TpContact *self_contact; + + g_assert (contacts->len == 1); + self_contact = g_ptr_array_index (contacts, 0); + + if (self_contact == self->priv->self_contact) + { + tp_g_signal_connect_object (self_contact, "notify::alias", + G_CALLBACK (mcd_account_self_contact_notify_alias_cb), + self, G_CONNECT_SWAPPED); + mcd_account_self_contact_notify_alias_cb (self, NULL, self_contact); + } + else + { + DEBUG ("self-contact '%s' has changed to '%s' since we asked to " + "upgrade it", tp_contact_get_identifier (self_contact), + tp_contact_get_identifier (self->priv->self_contact)); + } + + g_ptr_array_unref (contacts); + } + else + { + WARNING ("failed to prepare self-contact: %s", error->message); + g_clear_error (&error); + } + + g_object_unref (self); + tp_weak_ref_destroy (user_data); +} + +static void mcd_account_connection_ready_cb (McdAccount *account, McdConnection *connection) { + static const TpContactFeature contact_features[] = { + TP_CONTACT_FEATURE_ALIAS + }; McdAccountPrivate *priv = account->priv; gchar *nickname; TpConnection *tp_connection; @@ -4517,6 +4605,12 @@ mcd_account_connection_ready_cb (McdAccount *account, _mcd_account_set_normalized_name (account, tp_contact_get_identifier ( priv->self_contact)); + tp_connection_upgrade_contacts_async (tp_connection, + 1, &priv->self_contact, + G_N_ELEMENTS (contact_features), contact_features, + mcd_account_self_contact_upgraded_cb, + tp_weak_ref_new (account, NULL, NULL)); + /* FIXME: ideally, on protocols with server-stored nicknames, this should * only be done if the local Nickname has been changed since last time we * were online; Aliasing doesn't currently offer a way to tell whether @@ -4526,8 +4620,7 @@ mcd_account_connection_ready_cb (McdAccount *account, if (nickname != NULL) { - /* this is a no-op if the connection doesn't support it */ - _mcd_connection_set_nickname (connection, nickname); + mcd_account_send_nickname_to_connection (account, nickname); } g_free (nickname); @@ -4592,10 +4685,6 @@ _mcd_account_set_connection (McdAccount *account, McdConnection *connection) G_CALLBACK (mcd_account_connection_ready_cb), account); } - g_signal_connect_swapped (connection, "self-nickname-changed", - G_CALLBACK (mcd_account_connection_self_nickname_changed_cb), - account); - g_signal_connect (connection, "self-presence-changed", G_CALLBACK (on_conn_self_presence_changed), account); g_signal_connect (connection, "connection-status-changed", diff --git a/src/mcd-connection-priv.h b/src/mcd-connection-priv.h index 4aefa63..8f03f16 100644 --- a/src/mcd-connection-priv.h +++ b/src/mcd-connection-priv.h @@ -47,9 +47,6 @@ G_GNUC_INTERNAL void _mcd_connection_start_dispatching (McdConnection *self, G_GNUC_INTERNAL gboolean _mcd_connection_is_ready (McdConnection *self); -G_GNUC_INTERNAL void _mcd_connection_set_nickname (McdConnection *self, - const gchar *nickname); - G_GNUC_INTERNAL void _mcd_connection_set_avatar (McdConnection *self, const GArray *avatar, const gchar *mime_type); diff --git a/src/mcd-connection.c b/src/mcd-connection.c index 8792045..68ea8c8 100644 --- a/src/mcd-connection.c +++ b/src/mcd-connection.c @@ -105,7 +105,6 @@ struct _McdConnectionPrivate guint setting_avatar : 1; guint has_presence_if : 1; guint has_avatars_if : 1; - guint has_alias_if : 1; guint has_capabilities_if : 1; guint has_contact_capabilities_if : 1; guint has_power_saving_if : 1; @@ -128,8 +127,6 @@ struct _McdConnectionPrivate /* FALSE until connected and the supported presence statuses retrieved */ guint presence_info_ready : 1; - gchar *alias; - gboolean is_disposed; gboolean service_points_watched; @@ -164,7 +161,6 @@ enum { READY, SELF_PRESENCE_CHANGED, - SELF_NICKNAME_CHANGED, CONNECTION_STATUS_CHANGED, N_SIGNALS }; @@ -853,132 +849,6 @@ _mcd_connection_setup_avatar (McdConnection *connection) } static void -on_aliases_changed (TpConnection *proxy, const GPtrArray *aliases, - gpointer user_data, GObject *weak_object) -{ - McdConnectionPrivate *priv = user_data; - guint self_handle; - guint i; - - DEBUG ("called"); - - self_handle = tp_connection_get_self_handle (proxy); - - for (i = 0; i < aliases->len; i++) - { - GValueArray *structure = g_ptr_array_index (aliases, i); - - if (g_value_get_uint (structure->values) == self_handle) - { - const gchar *alias = g_value_get_string (structure->values + 1); - - DEBUG ("Our alias on %s changed to %s", - tp_proxy_get_object_path (proxy), alias); - - if (priv->alias == NULL || tp_strdiff (priv->alias, alias)) - { - g_free (priv->alias); - priv->alias = g_strdup (alias); - g_signal_emit (weak_object, signals[SELF_NICKNAME_CHANGED], - 0, alias); - } - break; - } - } -} - -static void -aliasing_set_aliases_cb (TpConnection *proxy, const GError *error, - gpointer user_data, GObject *weak_object) -{ - if (error) - { - g_warning ("%s: error: %s", G_STRFUNC, error->message); - } -} - -void -_mcd_connection_set_nickname (McdConnection *connection, - const gchar *nickname) -{ - McdConnectionPrivate *priv = connection->priv; - GHashTable *aliases; - TpHandle self_handle; - - if (!priv->has_alias_if) - return; - - DEBUG ("setting nickname '%s' using Aliasing", nickname); - - aliases = g_hash_table_new (NULL, NULL); - self_handle = tp_connection_get_self_handle (priv->tp_conn); - g_hash_table_insert (aliases, GUINT_TO_POINTER (self_handle), - (gchar *) nickname); - tp_cli_connection_interface_aliasing_call_set_aliases (priv->tp_conn, -1, - aliases, - aliasing_set_aliases_cb, - priv, NULL, - (GObject *)connection); - g_hash_table_unref (aliases); -} - -static void -_mcd_connection_get_aliases_cb (TpConnection *proxy, - GHashTable *aliases, - const GError *error, - gpointer user_data, - GObject *weak_object) -{ - McdConnectionPrivate *priv = user_data; - guint self_handle; - const gchar *alias; - - DEBUG ("called"); - - if (error != NULL) - { - DEBUG ("GetAliases([SelfHandle]) failed: %s", error->message); - return; - } - - self_handle = tp_connection_get_self_handle (proxy); - - alias = g_hash_table_lookup (aliases,GUINT_TO_POINTER (self_handle)); - - if (alias != NULL && - (priv->alias == NULL || tp_strdiff (priv->alias, alias))) - { - g_free (priv->alias); - priv->alias = g_strdup (alias); - g_signal_emit (weak_object, signals[SELF_NICKNAME_CHANGED], 0, - alias); - } -} - -static void -_mcd_connection_setup_alias (McdConnection *connection) -{ - McdConnectionPrivate *priv = connection->priv; - GArray *self_handle_array; - guint self_handle; - - self_handle_array = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1); - self_handle = tp_connection_get_self_handle (priv->tp_conn); - g_array_append_val (self_handle_array, self_handle); - - tp_cli_connection_interface_aliasing_connect_to_aliases_changed (priv->tp_conn, - on_aliases_changed, - priv, NULL, - (GObject *)connection, - NULL); - - tp_cli_connection_interface_aliasing_call_get_aliases - (priv->tp_conn, -1, self_handle_array, _mcd_connection_get_aliases_cb, - priv, NULL, (GObject *) connection); - g_array_unref (self_handle_array); -} - -static void _mcd_connection_setup_power_saving (McdConnection *connection) { McdConnectionPrivate *priv = connection->priv; @@ -1540,8 +1410,6 @@ on_connection_ready (GObject *source_object, GAsyncResult *result, (tp_conn, TP_IFACE_QUARK_CONNECTION_INTERFACE_SIMPLE_PRESENCE); priv->has_avatars_if = tp_proxy_has_interface_by_id (tp_conn, TP_IFACE_QUARK_CONNECTION_INTERFACE_AVATARS); - priv->has_alias_if = tp_proxy_has_interface_by_id (tp_conn, - TP_IFACE_QUARK_CONNECTION_INTERFACE_ALIASING); priv->has_capabilities_if = tp_proxy_has_interface_by_id (tp_conn, TP_IFACE_QUARK_CONNECTION_INTERFACE_CAPABILITIES); priv->has_contact_capabilities_if = tp_proxy_has_interface_by_id (tp_conn, @@ -1555,9 +1423,6 @@ on_connection_ready (GObject *source_object, GAsyncResult *result, if (priv->has_avatars_if) _mcd_connection_setup_avatar (connection); - if (priv->has_alias_if) - _mcd_connection_setup_alias (connection); - if (priv->has_power_saving_if) _mcd_connection_setup_power_saving (connection); @@ -1874,7 +1739,6 @@ _mcd_connection_finalize (GObject * object) McdConnection *connection = MCD_CONNECTION (object); McdConnectionPrivate *priv = MCD_CONNECTION_PRIV (connection); - g_free (priv->alias); if (priv->recognized_presences) g_hash_table_unref (priv->recognized_presences); @@ -1916,11 +1780,6 @@ _mcd_connection_release_tp_connection (McdConnection *connection) tp_clear_object (&priv->tp_conn); } - /* the interface proxies obtained from this connection must be deleted, too - */ - g_free (priv->alias); - priv->alias = NULL; - if (priv->recognized_presences) g_hash_table_remove_all (priv->recognized_presences); @@ -2272,12 +2131,6 @@ mcd_connection_class_init (McdConnectionClass * klass) NULL, NULL, NULL, G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING); - signals[SELF_NICKNAME_CHANGED] = g_signal_new ("self-nickname-changed", - G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, - NULL, NULL, g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - signals[CONNECTION_STATUS_CHANGED] = g_signal_new ( "connection-status-changed", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, -- 1.7.10.4