From 9cba4d57fcf4a808317461f2e14845c613a70c65 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 26 Jul 2012 11:11:18 +0200 Subject: [PATCH] TpAccountManager: add _prepare_all_async() to prepare all proxies/contacts This is convenient function for plugins and libraries. https://bugs.freedesktop.org/show_bug.cgi?id=52531 --- docs/reference/telepathy-glib-sections.txt | 3 + telepathy-glib/account-manager.c | 54 +++++++++++ telepathy-glib/account-manager.h | 9 ++ telepathy-glib/simple-client-factory-internal.h | 4 + telepathy-glib/simple-client-factory.c | 112 +++++++++++++++++++++++ 5 files changed, 182 insertions(+) diff --git a/docs/reference/telepathy-glib-sections.txt b/docs/reference/telepathy-glib-sections.txt index f6e20b0..38062dd 100644 --- a/docs/reference/telepathy-glib-sections.txt +++ b/docs/reference/telepathy-glib-sections.txt @@ -5325,6 +5325,9 @@ TP_ACCOUNT_MANAGER_FEATURE_CORE tp_account_manager_is_prepared tp_account_manager_prepare_async tp_account_manager_prepare_finish + +tp_account_manager_prepare_all_async +tp_account_manager_prepare_all_finish tp_account_manager_get_feature_quark_core diff --git a/telepathy-glib/account-manager.c b/telepathy-glib/account-manager.c index 6d31a01..46fa558 100644 --- a/telepathy-glib/account-manager.c +++ b/telepathy-glib/account-manager.c @@ -1447,6 +1447,60 @@ tp_account_manager_prepare_finish (TpAccountManager *manager, } /** + * tp_account_manager_prepare_all_async: + * @self: a #TpAccountManager object + * @callback: a callback to call when the operation finishes + * @user_data: data to pass to @callback + * + * Prepare %TP_ACCOUNT_MANAGER_CORE on @self and ensure that all #TpAccount, + * #TpConnection, #TpChannel and #TpContact created through @self's + * #TpProxy:factory have all the features prepared. + * + * This is especially useful to libraries or plugins who cannot guarantee to be + * the only user of @self across the process. This happens when using + * tp_account_manager_dup(). In that case adding features on the factory would + * not apply on already existing objects; calling this function ensure they are. + * + * Since: 0.UNRELEASED + */ +void +tp_account_manager_prepare_all_async (TpAccountManager *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + + g_return_if_fail (TP_IS_ACCOUNT_MANAGER (self)); + + result = g_simple_async_result_new ((GObject *) self, callback, user_data, + tp_account_manager_prepare_all_async); + + _tp_simple_client_factory_prepare_all (tp_proxy_get_factory (self), self, + result); + + g_object_unref (result); +} + +/** + * tp_account_manager_prepare_all_finish: + * @self: a #TpAccountManager + * @result: a #GAsyncResult + * @error: a #GError to fill + * + * Finishes tp_account_manager_prepare_all_async() + * + * Returns: %TRUE on success, %FALSE otherwise. + * Since: 0.UNRELEASED + */ +gboolean +tp_account_manager_prepare_all_finish (TpAccountManager *self, + GAsyncResult *result, + GError **error) +{ + _tp_implement_finish_void (self, tp_account_manager_prepare_all_async); +} + +/** * tp_account_manager_enable_restart: * @manager: a #TpAccountManager * diff --git a/telepathy-glib/account-manager.h b/telepathy-glib/account-manager.h index 7c373ed..a2ce071 100644 --- a/telepathy-glib/account-manager.h +++ b/telepathy-glib/account-manager.h @@ -126,6 +126,15 @@ gboolean tp_account_manager_prepare_finish (TpAccountManager *manager, GError **error); #endif +_TP_AVAILABLE_IN_UNRELEASED +void tp_account_manager_prepare_all_async (TpAccountManager *self, + GAsyncReadyCallback callback, + gpointer user_data); +_TP_AVAILABLE_IN_UNRELEASED +gboolean tp_account_manager_prepare_all_finish (TpAccountManager *self, + GAsyncResult *result, + GError **error); + void tp_account_manager_enable_restart (TpAccountManager *manager); G_END_DECLS diff --git a/telepathy-glib/simple-client-factory-internal.h b/telepathy-glib/simple-client-factory-internal.h index 495052f..cf8773c 100644 --- a/telepathy-glib/simple-client-factory-internal.h +++ b/telepathy-glib/simple-client-factory-internal.h @@ -29,6 +29,10 @@ G_BEGIN_DECLS void _tp_simple_client_factory_insert_proxy (TpSimpleClientFactory *self, gpointer proxy); +void _tp_simple_client_factory_prepare_all (TpSimpleClientFactory *self, + TpAccountManager *manager, + GSimpleAsyncResult *result); + TpChannelRequest *_tp_simple_client_factory_ensure_channel_request ( TpSimpleClientFactory *self, const gchar *object_path, diff --git a/telepathy-glib/simple-client-factory.c b/telepathy-glib/simple-client-factory.c index 34ad54c..b563d0c 100644 --- a/telepathy-glib/simple-client-factory.c +++ b/telepathy-glib/simple-client-factory.c @@ -1237,3 +1237,115 @@ _tp_simple_client_factory_ensure_channel_dispatch_operation ( return dispatch; } + +static void +prepare_all_contacts_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + TpSimpleClientFactory *self = (TpSimpleClientFactory *) source; + GSimpleAsyncResult *my_result = user_data; + guint count; + GError *error = NULL; + + if (!tp_simple_client_factory_upgrade_contacts_finish (self, result, NULL, + &error)) + { + g_simple_async_result_take_error (my_result, error); + } + + count = g_simple_async_result_get_op_res_gssize (my_result); + count--; + g_simple_async_result_set_op_res_gssize (my_result, count); + + if (count == 0) + g_simple_async_result_complete (my_result); + + g_object_unref (my_result); +} + +static void +prepare_all_proxy_cb (GObject *proxy, + GAsyncResult *result, + gpointer user_data) +{ + TpSimpleClientFactory *self = tp_proxy_get_factory (proxy); + GSimpleAsyncResult *my_result = user_data; + guint count; + GError *error = NULL; + + if (!tp_proxy_prepare_finish (proxy, result, &error)) + { + /* Ignore error if the proxy got invalidated in the meantime. In all cases + * just continue to prepare as much as possible. */ + if (tp_proxy_get_invalidated (proxy) != NULL) + g_clear_error (&error); + else + g_simple_async_result_take_error (my_result, error); + } + + count = g_simple_async_result_get_op_res_gssize (my_result); + count--; + + if (TP_IS_CONNECTION (proxy)) + { + TpConnection *connection = (TpConnection *) proxy; + GPtrArray *contacts; + + contacts = _tp_contacts_from_values (connection->priv->contacts); + if (contacts != NULL && contacts->len != 0) + { + tp_simple_client_factory_upgrade_contacts_async (self, connection, + contacts->len, (TpContact * const *) contacts->pdata, + prepare_all_contacts_cb, g_object_ref (my_result)); + count++; + } + tp_clear_pointer (&contacts, g_ptr_array_unref); + } + + g_simple_async_result_set_op_res_gssize (my_result, count); + + if (count == 0) + g_simple_async_result_complete (my_result); + + g_object_unref (my_result); +} + +void +_tp_simple_client_factory_prepare_all (TpSimpleClientFactory *self, + TpAccountManager *manager, + GSimpleAsyncResult *result) +{ + GHashTableIter iter; + gpointer proxy; + guint count = 0; + + tp_proxy_prepare_async (manager, NULL, + prepare_all_proxy_cb, g_object_ref (result)); + count++; + + g_hash_table_iter_init (&iter, self->priv->proxy_cache); + while (g_hash_table_iter_next (&iter, NULL, &proxy)) + { + GArray *features = NULL; + + if (TP_IS_ACCOUNT (proxy)) + features = tp_simple_client_factory_dup_account_features (self, + (TpAccount *) proxy); + else if (TP_IS_CONNECTION (proxy)) + features = tp_simple_client_factory_dup_connection_features (self, + (TpConnection *) proxy); + else if (TP_IS_CHANNEL (proxy)) + features = tp_simple_client_factory_dup_channel_features (self, + (TpChannel *) proxy); + + tp_proxy_prepare_async (proxy, + (features != NULL) ? (const GQuark *) features->data : NULL, + prepare_all_proxy_cb, g_object_ref (result)); + count++; + + tp_clear_pointer (&features, g_array_unref); + } + + g_simple_async_result_set_op_res_gssize (result, count); +} -- 1.7.10.4