/* * account-manager.c - proxy for the Ytstenut account manager * * Copyright (C) 2009 Collabora Ltd. * Copyright (C) 2009 Nokia Corporation * Copyright (C) 2011 Intel Corp. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "account-manager.h" #include "client-factory.h" #include #include #include #include #include #include "_gen/interfaces.h" #include "_gen/cli-account-manager-body.h" #define DEBUG(msg, ...) \ g_debug ("%s: " msg, G_STRFUNC, ##__VA_ARGS__) /** * SECTION:account-manager * @title: TpYtsAccountManager * @short_description: proxy object for the Ytstenut account manager * * The #TpYtsAccountManager object is used to communicate with the Ytstenut * AccountManager service. It is a proxy object for the DBus object running * in a telepathy service. * * There is one predefined Ytstenut account, which is used to send and receive * Ytstenut messages. You can access the account using the * tp_yts_account_manager_get_account_async() function. * * The Ytstenut account will be kept online as long as one client has signified * interest in it. The tp_yts_account_manager_hold() function can be used to * signify that this client is interested in the Ytstenut account. Conversely, * calling tp_yts_account_manager_release() signifies that this client is no * longer interested in the Ytstenut account. */ /** * TpYtsAccountManager: * * The Ytstenut Account Manager holds information about the Ytstenut account * and controls its presence. */ /** * TpYtsAccountManagerClass: * * The class of a #TpYtsAccountManager. */ /** * TP_YTS_ACCOUNT_MANAGER_OBJECT_PATH: * * The DBus object path to the Ytstenut account. */ #define MC5_BUS_NAME "org.freedesktop.Telepathy.MissionControl5" G_DEFINE_TYPE (TpYtsAccountManager, tp_yts_account_manager, TP_TYPE_PROXY); struct _TpYtsAccountManagerPrivate { /* We have to store this and not simply subclass it because that * would change TpProxy:object-path from * /org/freedesktop/Telepathy/AccountManager to * /com/meego/xpmn/ytstenut/AccountManager which would mean loads of * things (like how TpAM calls GetAll on ofdTp.AM) would stop * working. This is a shame. Oh well. */ TpAccountManager *account_manager; }; static void tp_yts_account_manager_init (TpYtsAccountManager *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TYPE_YTS_ACCOUNT_MANAGER, TpYtsAccountManagerPrivate); } static void tp_yts_account_manager_dispose (GObject *object) { TpYtsAccountManager *self = TP_YTS_ACCOUNT_MANAGER (object); TpYtsAccountManagerPrivate *priv = self->priv; tp_clear_object (&priv->account_manager); G_OBJECT_CLASS (tp_yts_account_manager_parent_class)->dispose (object); } static void tp_yts_account_manager_class_init (TpYtsAccountManagerClass *klass) { GObjectClass *object_class = (GObjectClass *) klass; TpProxyClass *proxy_class = (TpProxyClass *) klass; GType tp_type = TP_TYPE_YTS_ACCOUNT_MANAGER; g_type_class_add_private (klass, sizeof (TpYtsAccountManagerPrivate)); object_class->dispose = tp_yts_account_manager_dispose; proxy_class->interface = TP_YTS_IFACE_QUARK_ACCOUNT_MANAGER; tp_proxy_init_known_interfaces (); tp_proxy_or_subclass_hook_on_interface_add (tp_type, tp_yts_account_manager_add_signals); tp_proxy_subclass_add_error_mapping (tp_type, TP_ERROR_PREFIX, TP_ERRORS, TP_TYPE_ERROR); } /** * tp_yts_account_manager_new: * @bus_daemon: Proxy for the D-Bus daemon * * Convenience function to create a new account manager proxy. * * Use tp_yts_account_manager_dup() instead if you want an account manager proxy * on the starter or session bus (which is almost always the right thing for * Telepathy). * * Returns: a new reference to an account manager proxy */ TpYtsAccountManager * tp_yts_account_manager_new (TpDBusDaemon *bus_daemon) { TpYtsAccountManager *self; TpSimpleClientFactory *factory; g_return_val_if_fail (TP_IS_DBUS_DAEMON (bus_daemon), NULL); factory = tp_yts_client_factory_new (bus_daemon); self = TP_YTS_ACCOUNT_MANAGER (g_object_new (TP_TYPE_YTS_ACCOUNT_MANAGER, "dbus-daemon", bus_daemon, "dbus-connection", ((TpProxy *) bus_daemon)->dbus_connection, "bus-name", MC5_BUS_NAME, "object-path", TP_YTS_ACCOUNT_MANAGER_OBJECT_PATH, "factory", factory, NULL)); self->priv->account_manager = tp_account_manager_new_with_factory (factory); g_object_unref (factory); return self; } static gpointer starter_account_manager_proxy = NULL; /** * tp_yts_account_manager_dup: * * Returns an account manager proxy on the D-Bus daemon on which this * process was activated (if it was launched by D-Bus service activation), or * the session bus (otherwise). * * The returned #TpYtsAccountManager is cached; the same #TpYtsAccountManager * object will be returned by this function repeatedly, as long as at least one * reference exists. * * Returns: (transfer full): an account manager proxy on the starter or session * bus, or %NULL if it wasn't possible to get a dbus daemon proxy for * the appropriate bus */ TpYtsAccountManager * tp_yts_account_manager_dup (void) { TpDBusDaemon *dbus; TpYtsAccountManager *self; if (starter_account_manager_proxy != NULL) return g_object_ref (starter_account_manager_proxy); dbus = tp_dbus_daemon_dup (NULL); if (dbus == NULL) return NULL; starter_account_manager_proxy = tp_yts_account_manager_new (dbus); g_assert (starter_account_manager_proxy != NULL); g_object_add_weak_pointer (starter_account_manager_proxy, &starter_account_manager_proxy); g_object_unref (dbus); self = starter_account_manager_proxy; tp_account_manager_set_default (self->priv->account_manager); return starter_account_manager_proxy; } /** * tp_yts_account_manager_ensure_account: * @self: a #TpYtsAccountManager * @path: the account object path * @error: a #GError to fill when an error is encountered * * Using the #TpYtsAccountManager ensure an account with object path * @path. This should be used instead of tp_account_new() as it means * the #TpYtsClientFactory will be propagated through to the new * account and so new channel objects will be turned into * #TpYtsChannels. * * Returns: a #TpAccount */ TpAccount * tp_yts_account_manager_ensure_account (TpYtsAccountManager *self, const gchar *path, GError **error) { TpSimpleClientFactory *factory; g_return_val_if_fail (TP_IS_YTS_ACCOUNT_MANAGER (self), NULL); g_return_val_if_fail (!tp_str_empty (path), NULL); factory = tp_proxy_get_factory (self->priv->account_manager); return tp_simple_client_factory_ensure_account (factory, path, NULL, error); } static void on_account_prepared (GObject *source, GAsyncResult *result, gpointer user_data) { GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); GError *error = NULL; if (!tp_proxy_prepare_finish (source, result, &error)) { DEBUG ("Failed to prepare the TpAccount: %s", error->message); g_simple_async_result_set_from_error (res, error); g_clear_error (&error); /* get rid of the account */ g_object_unref (source); } else { g_simple_async_result_set_op_res_gpointer (res, source, g_object_unref); } g_simple_async_result_complete (res); g_object_unref (res); } static void on_account_manager_get_account_returned (TpProxy *proxy, const GValue *value, const GError *error, gpointer user_data, GObject *weak_object) { TpYtsAccountManager *self = TP_YTS_ACCOUNT_MANAGER (weak_object); GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); TpAccount *account; GError *err = NULL; const gchar *path; if (error == NULL) { path = g_value_get_boxed (value); account = tp_simple_client_factory_ensure_account ( tp_proxy_get_factory (self->priv->account_manager), path, NULL, &err); if (err == NULL) { tp_proxy_prepare_async (account, NULL, on_account_prepared, g_object_ref (res)); return; } else { DEBUG ("Failed to create TpAccount: %s", err->message); g_simple_async_result_set_from_error (res, err); g_clear_error (&err); } } else { DEBUG ("Failed to get account path: %s", error->message); g_simple_async_result_set_from_error (res, error); } g_simple_async_result_complete_in_idle (res); } /** * tp_yts_account_manager_get_account_async: * @self: The proxy object. * @cancellable: Currently ignored. * @callback: A callback which should be called when the result is ready. * @user_data: Data to pass to the callback. * * Start an asynchronous operation to get the Ytstenut account. */ void tp_yts_account_manager_get_account_async (TpYtsAccountManager *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *res; g_return_if_fail (TP_IS_YTS_ACCOUNT_MANAGER (self)); res = g_simple_async_result_new (G_OBJECT (self), callback, user_data, tp_yts_account_manager_get_account_async); tp_cli_dbus_properties_call_get (TP_PROXY (self), -1, TP_YTS_IFACE_ACCOUNT_MANAGER, "Account", on_account_manager_get_account_returned, res, g_object_unref, G_OBJECT (self)); } /** * tp_yts_account_manager_get_account_finish: * @self: The proxy object. * @result: The result object passed to the callback. * @error: An error will be placed here. * * Complete an asynchronous operation to get the Ytstenut account. * * The returned #TpAccount is guaranteed to have been prepared using * tp_proxy_prepare() for the CORE feature. * * Returns: A newly allocated #TpAccount proxy, which you can use to access * the Ytstenut account. If the operation failed %NULL will be returned. */ TpAccount * tp_yts_account_manager_get_account_finish (TpYtsAccountManager *self, GAsyncResult *result, GError **error) { GSimpleAsyncResult *res; g_return_val_if_fail (TP_IS_YTS_ACCOUNT_MANAGER (self), NULL); g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL); res = G_SIMPLE_ASYNC_RESULT (result); g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), tp_yts_account_manager_get_account_async), NULL); if (g_simple_async_result_propagate_error (res, error)) return NULL; return g_object_ref (g_simple_async_result_get_op_res_gpointer (res)); } static void on_account_manager_hold_returned (TpYtsAccountManager *self, const GError *error, gpointer user_data, GObject *weak_object) { if (error != NULL) { DEBUG ("%s.Hold() call failed: %s", TP_YTS_IFACE_ACCOUNT_MANAGER, error->message); } } /** * tp_yts_account_manager_hold: * @self: The proxy object. * * Indicate that this client is interested in the Ytstenut account. As long as * one or more clients are interested, an effort will be made to keep the * account logged in and have an available presence. * * This method completes asynchronously, and the results may not be immediately * apparent. */ void tp_yts_account_manager_hold (TpYtsAccountManager *self) { g_return_if_fail (TP_IS_YTS_ACCOUNT_MANAGER (self)); tp_yts_account_manager_call_hold (self, -1, on_account_manager_hold_returned, NULL, NULL, G_OBJECT (self)); } static void on_account_manager_release_returned (TpYtsAccountManager *self, const GError *error, gpointer user_data, GObject *weak_object) { if (error != NULL) { DEBUG ("%s.Release() call failed: %s", TP_YTS_IFACE_ACCOUNT_MANAGER, error->message); } } /** * tp_yts_account_manager_release: * @self: The proxy object. * * Indicate that this client is no longer interested in the Ytstenut account. * Once no more clients are interested, the Ytstenut account will be set to * offline presence. * * This method completes asynchronously, and the results may not be immediately * apparent. */ void tp_yts_account_manager_release (TpYtsAccountManager *self) { g_return_if_fail (TP_IS_YTS_ACCOUNT_MANAGER (self)); tp_yts_account_manager_call_release (self, -1, on_account_manager_release_returned, NULL, NULL, G_OBJECT (self)); }