[folks] Tests: port to verbatim copy of tp-glib files
- From: Xavier Claessens <xclaesse src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [folks] Tests: port to verbatim copy of tp-glib files
- Date: Wed, 28 Mar 2012 12:17:20 +0000 (UTC)
commit 109133c590822eb93fa9c8245fdb2f7347f5acf6
Author: Xavier Claessens <xavier claessens collabora co uk>
Date: Tue Mar 27 18:05:12 2012 +0200
Tests: port to verbatim copy of tp-glib files
tests/lib/telepathy/contactlist/Makefile.am | 19 +-
tests/lib/telepathy/contactlist/account-manager.h | 66 -
tests/lib/telepathy/contactlist/account.c | 341 ----
tests/lib/telepathy/contactlist/account.h | 60 -
tests/lib/telepathy/contactlist/backend.c | 253 ++--
tests/lib/telepathy/contactlist/backend.h | 14 +-
tests/lib/telepathy/contactlist/conn.c | 972 ---------
tests/lib/telepathy/contactlist/conn.h | 75 -
.../telepathy/contactlist/contact-list-manager.c | 2139 ++++++--------------
.../telepathy/contactlist/contact-list-manager.h | 103 +-
tests/lib/telepathy/contactlist/contact-list.c | 632 ------
tests/lib/telepathy/contactlist/contact-list.h | 118 --
tests/lib/telepathy/contactlist/contacts-conn.c | 1392 +++++++++++++
tests/lib/telepathy/contactlist/contacts-conn.h | 190 ++
tests/lib/telepathy/contactlist/debug.h | 3 +
...{account-manager.c => simple-account-manager.c} | 146 +-
.../telepathy/contactlist/simple-account-manager.h | 66 +
tests/lib/telepathy/contactlist/simple-account.c | 579 ++++++
tests/lib/telepathy/contactlist/simple-account.h | 69 +
tests/lib/telepathy/contactlist/simple-conn.c | 452 +++++
tests/lib/telepathy/contactlist/simple-conn.h | 77 +
tests/lib/telepathy/contactlist/textchan-null.c | 571 ++++++
tests/lib/telepathy/contactlist/textchan-null.h | 137 ++
.../telepathy/contactlist/tp-test-contactlist.h | 7 +-
tests/telepathy/individual-properties.vala | 4 +-
25 files changed, 4389 insertions(+), 4096 deletions(-)
---
diff --git a/tests/lib/telepathy/contactlist/Makefile.am b/tests/lib/telepathy/contactlist/Makefile.am
index f419bd4..1578f67 100644
--- a/tests/lib/telepathy/contactlist/Makefile.am
+++ b/tests/lib/telepathy/contactlist/Makefile.am
@@ -18,18 +18,21 @@ noinst_LTLIBRARIES = libtp-test-contactlist.la
libtp_test_contactlist_la_SOURCES = \
_gen/param-spec-struct.h \
- account.c \
- account.h \
- account-manager.c \
- account-manager.h \
backend.c \
backend.h \
- conn.c \
- conn.h \
- contact-list.c \
- contact-list.h \
contact-list-manager.c \
contact-list-manager.h \
+ contacts-conn.c \
+ contacts-conn.h \
+ debug.h \
+ simple-account.c \
+ simple-account.h \
+ simple-account-manager.c \
+ simple-account-manager.h \
+ simple-conn.c \
+ simple-conn.h \
+ textchan-null.c \
+ textchan-null.h \
util.c \
util.h \
$(NULL)
diff --git a/tests/lib/telepathy/contactlist/backend.c b/tests/lib/telepathy/contactlist/backend.c
index 663322b..5defd35 100644
--- a/tests/lib/telepathy/contactlist/backend.c
+++ b/tests/lib/telepathy/contactlist/backend.c
@@ -24,38 +24,31 @@
#include <telepathy-glib/dbus.h>
#include <telepathy-glib/svc-account.h>
-#include "account.h"
-#include "account-manager.h"
-#include "conn.h"
-#include "contact-list.h"
+#include "simple-account.h"
+#include "simple-account-manager.h"
#include "util.h"
+#include "contacts-conn.h"
#include "backend.h"
struct _TpTestsBackendPrivate
{
- TpAccountManager *am_proxy;
TpDBusDaemon *daemon;
- TpTestsAccountManager *account_manager;
+ TpTestsSimpleAccountManager *account_manager;
+ TpAccountManager *client_am;
GList *accounts;
};
typedef struct
{
- TpTestsAccount *account;
- TpBaseConnection *conn;
- gchar *bus_name;
+ TpTestsSimpleAccount *account;
+ TpBaseConnection *base_connection;
+ TpConnection *client_conn;
gchar *object_path;
} AccountData;
G_DEFINE_TYPE (TpTestsBackend, tp_tests_backend, G_TYPE_OBJECT)
-enum
-{
- PROP_CONNECTION = 1,
- N_PROPS
-};
-
static void
tp_tests_backend_init (TpTestsBackend *self)
{
@@ -79,53 +72,12 @@ tp_tests_backend_finalize (GObject *object)
}
static void
-tp_tests_backend_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *spec)
-{
- TpTestsBackend *self = TP_TESTS_BACKEND (object);
-
- switch (property_id)
- {
- case PROP_CONNECTION:
- g_value_set_object (value, tp_tests_backend_get_connection (self));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec);
- }
-}
-
-static void
-tp_tests_backend_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *spec)
-{
- switch (property_id)
- {
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec);
- }
-}
-
-static void
tp_tests_backend_class_init (TpTestsBackendClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GParamSpec *param_spec;
g_type_class_add_private (klass, sizeof (TpTestsBackendPrivate));
object_class->finalize = tp_tests_backend_finalize;
- object_class->get_property = tp_tests_backend_get_property;
- object_class->set_property = tp_tests_backend_set_property;
-
- param_spec = g_param_spec_object ("connection", "Connection",
- "The base ContactListConnection",
- TP_TESTS_TYPE_CONTACT_LIST_CONNECTION,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
}
TpTestsBackend *
@@ -200,79 +152,152 @@ tp_tests_backend_set_up (TpTestsBackend *self)
TP_ACCOUNT_MANAGER_BUS_NAME, error->message);
}
- priv->account_manager = tp_tests_account_manager_new ();
+ priv->account_manager = tp_tests_object_new_static_class (
+ TP_TESTS_TYPE_SIMPLE_ACCOUNT_MANAGER, NULL);
tp_dbus_daemon_register_object (priv->daemon, TP_ACCOUNT_MANAGER_OBJECT_PATH,
priv->account_manager);
- priv->am_proxy = tp_account_manager_dup ();
+ priv->client_am = tp_account_manager_dup ();
+}
+
+static void
+fill_default_roster (AccountData *data)
+{
+ TpTestsContactsConnection *conn = (TpTestsContactsConnection *) data->base_connection;
+ TpTestsContactListManager *manager;
+ TpHandleRepoIface *repo;
+ TpHandle handle;
+ const gchar *str;
+ TpTestsContactsConnectionPresenceStatusIndex presence;
+ GPtrArray *info;
+ const gchar *single_value[] = { NULL, NULL };
+ GQuark conn_features[] = { TP_CONNECTION_FEATURE_CONNECTED, 0 };
+
+ repo = tp_base_connection_get_handles (data->base_connection,
+ TP_HANDLE_TYPE_CONTACT);
+ manager = tp_tests_contacts_connection_get_contact_list_manager (conn);
+
+ /* Create some contacts and fill some info */
+ handle = tp_handle_ensure (repo, "guillaume example com", NULL, NULL);
+ tp_tests_contact_list_manager_request_subscription (manager, 1, &handle, "");
+
+ handle = tp_handle_ensure (repo, "sjoerd example com", NULL, NULL);
+ tp_tests_contact_list_manager_request_subscription (manager, 1, &handle, "");
+
+ handle = tp_handle_ensure (repo, "travis example com", NULL, NULL);
+ tp_tests_contact_list_manager_request_subscription (manager, 1, &handle, "");
+
+ handle = tp_handle_ensure (repo, "olivier example com", NULL, NULL);
+ tp_tests_contact_list_manager_request_subscription (manager, 1, &handle, "");
+ str = "Olivier";
+ tp_tests_contacts_connection_change_aliases (conn, 1, &handle, &str);
+ presence = TP_TESTS_CONTACTS_CONNECTION_STATUS_AWAY;
+ str = "";
+ tp_tests_contacts_connection_change_presences (conn, 1, &handle, &presence, &str);
+ tp_tests_contact_list_manager_add_to_group (manager, "Montreal", handle);
+ tp_tests_contact_list_manager_add_to_group (manager, "Francophones", handle);
+ info = g_ptr_array_new_with_free_func ((GDestroyNotify) g_value_array_free);
+ single_value[0] = "+15142345678";
+ g_ptr_array_add (info, tp_value_array_build (3,
+ G_TYPE_STRING, "tel",
+ G_TYPE_STRV, NULL,
+ G_TYPE_STRV, single_value,
+ G_TYPE_INVALID));
+ single_value[0] = "Olivier Crete";
+ g_ptr_array_add (info, tp_value_array_build (3,
+ G_TYPE_STRING, "fn",
+ G_TYPE_STRV, NULL,
+ G_TYPE_STRV, single_value,
+ G_TYPE_INVALID));
+ single_value[0] = "olivier example com";
+ g_ptr_array_add (info, tp_value_array_build (3,
+ G_TYPE_STRING, "email",
+ G_TYPE_STRV, NULL,
+ G_TYPE_STRV, single_value,
+ G_TYPE_INVALID));
+ single_value[0] = "ocrete.example.com";
+ g_ptr_array_add (info, tp_value_array_build (3,
+ G_TYPE_STRING, "url",
+ G_TYPE_STRV, NULL,
+ G_TYPE_STRV, single_value,
+ G_TYPE_INVALID));
+ tp_tests_contacts_connection_change_contact_info (conn, handle, info);
+ g_ptr_array_unref (info);
+
+ handle = tp_handle_ensure (repo, "christian example com", NULL, NULL);
+ tp_tests_contact_list_manager_request_subscription (manager, 1, &handle, "");
+
+ handle = tp_handle_ensure (repo, "geraldine example com", NULL, NULL);
+ tp_tests_contact_list_manager_request_subscription (manager, 1, &handle, "");
+
+ handle = tp_handle_ensure (repo, "helen example com", NULL, NULL);
+ tp_tests_contact_list_manager_request_subscription (manager, 1, &handle, "");
+
+ handle = tp_handle_ensure (repo, "wim example com", NULL, NULL);
+ tp_tests_contact_list_manager_request_subscription (manager, 1, &handle, "");
+
+ /* Run until connected */
+ tp_cli_connection_call_connect (data->client_conn, -1, NULL, NULL, NULL, NULL);
+ tp_tests_proxy_run_until_prepared (data->client_conn, conn_features);
}
/**
* tp_tests_backend_add_account:
* @self:
- * @protocol_name:
* @user_id:
- * @connection_manager_name:
- * @account_name:
*
* Return value: (transfer none):
*/
gpointer
tp_tests_backend_add_account (TpTestsBackend *self,
- const gchar *protocol_name,
+ const gchar *protocol,
const gchar *user_id,
- const gchar *connection_manager_name,
- const gchar *account_name)
+ const gchar *cm_name,
+ const gchar *account)
{
TpTestsBackendPrivate *priv = self->priv;
- TpHandleRepoIface *handle_repo;
- TpHandle self_handle;
- gchar *object_path;
AccountData *data;
+ gchar *conn_path;
GError *error = NULL;
data = g_slice_new (AccountData);
/* Set up a contact list connection */
- data->conn =
- TP_BASE_CONNECTION (tp_tests_contact_list_connection_new (user_id,
- protocol_name, 0, 0));
-
- tp_base_connection_register (data->conn, connection_manager_name,
- &data->bus_name, &data->object_path, &error);
- if (error != NULL)
- {
- g_error ("Failed to register connection %p: %s", data->conn,
- error->message);
- }
-
- handle_repo = tp_base_connection_get_handles (data->conn,
- TP_HANDLE_TYPE_CONTACT);
- self_handle = tp_handle_ensure (handle_repo, user_id, NULL, &error);
- if (error != NULL)
- {
- g_error ("Couldn't ensure self handle '%s': %s", user_id, error->message);
- }
-
- tp_base_connection_set_self_handle (data->conn, self_handle);
- tp_base_connection_change_status (data->conn,
- TP_CONNECTION_STATUS_CONNECTED, TP_CONNECTION_STATUS_REASON_REQUESTED);
+ data->base_connection = tp_tests_object_new_static_class (
+ TP_TESTS_TYPE_CONTACTS_CONNECTION,
+ "account", user_id,
+ "protocol", protocol,
+ NULL);
+ tp_base_connection_register (data->base_connection, cm_name,
+ NULL, &conn_path, &error);
+ g_assert_no_error (error);
+
+ data->client_conn = tp_connection_new (priv->daemon, NULL, conn_path,
+ &error);
+ g_assert_no_error (error);
/* Create an account */
- data->account = tp_tests_account_new (data->object_path);
- object_path =
- g_strdup_printf ("%s%s/%s/%s", TP_ACCOUNT_OBJECT_PATH_BASE,
- connection_manager_name, protocol_name, account_name);
- tp_dbus_daemon_register_object (priv->daemon, object_path, data->account);
+ data->account = tp_tests_object_new_static_class (
+ TP_TESTS_TYPE_SIMPLE_ACCOUNT, NULL);
+ data->object_path = g_strdup_printf ("%s%s/%s/%s", TP_ACCOUNT_OBJECT_PATH_BASE,
+ cm_name, protocol, account);
+ tp_dbus_daemon_register_object (priv->daemon, data->object_path,
+ data->account);
- /* Add the account to the account manager */
- tp_tests_account_manager_add_account (priv->account_manager, object_path);
+ /* Set the connection on the account */
+ tp_tests_simple_account_set_connection (data->account, conn_path);
- g_free (object_path);
+ /* Add the account to the account manager */
+ tp_tests_simple_account_manager_add_account (priv->account_manager,
+ data->object_path, TRUE);
/* Add the account to the list of accounts and return a handle to it */
priv->accounts = g_list_prepend (priv->accounts, data);
+ fill_default_roster (data);
+
+ g_free (conn_path);
+
return data;
}
@@ -293,21 +318,19 @@ tp_tests_backend_remove_account (TpTestsBackend *self,
data = (AccountData *) handle;
/* Remove the account from the account manager */
- tp_tests_account_manager_remove_account (priv->account_manager,
+ tp_tests_simple_account_manager_remove_account (priv->account_manager,
data->object_path);
+ tp_tests_simple_account_removed (data->account);
/* Disconnect it */
- tp_base_connection_change_status (data->conn,
+ tp_base_connection_change_status (data->base_connection,
TP_CONNECTION_STATUS_DISCONNECTED, TP_CONNECTION_STATUS_REASON_REQUESTED);
- tp_svc_account_emit_removed (data->account);
-
tp_dbus_daemon_unregister_object (priv->daemon, data->account);
- tp_clear_object (&data->account);
-
- tp_clear_object (&data->conn);
- g_free (data->bus_name);
+ tp_clear_object (&data->account);
+ tp_clear_object (&data->base_connection);
+ tp_clear_object (&data->client_conn);
g_free (data->object_path);
}
@@ -318,8 +341,8 @@ tp_tests_backend_tear_down (TpTestsBackend *self)
GError *error = NULL;
/* Make sure all dbus trafic is done */
- tp_tests_proxy_run_until_dbus_queue_processed (priv->am_proxy);
- g_clear_object (&priv->am_proxy);
+ tp_tests_proxy_run_until_dbus_queue_processed (priv->client_am);
+ g_clear_object (&priv->client_am);
tp_dbus_daemon_unregister_object (priv->daemon, priv->account_manager);
tp_clear_object (&priv->account_manager);
@@ -336,23 +359,25 @@ tp_tests_backend_tear_down (TpTestsBackend *self)
}
/**
- * tp_tests_backend_get_connection:
+ * tp_tests_backend_get_connection_for_handle:
* @self: the backend
*
* Returns: (transfer none): the contact list connection or %NULL.
*/
-TpTestsContactListConnection *
-tp_tests_backend_get_connection (TpTestsBackend *self)
+TpTestsContactsConnection *
+tp_tests_backend_get_connection_for_handle (TpTestsBackend *self,
+ gpointer handle)
{
+ TpTestsBackendPrivate *priv = self->priv;
AccountData *data;
g_return_val_if_fail (TP_TESTS_IS_BACKEND (self), NULL);
- if (self->priv->accounts == NULL)
+ if (g_list_find (priv->accounts, handle) == NULL)
{
return NULL;
}
- data = (AccountData *) self->priv->accounts->data;
- return TP_TESTS_CONTACT_LIST_CONNECTION (data->conn);
+ data = (AccountData *) handle;
+ return TP_TESTS_CONTACTS_CONNECTION (data->base_connection);
}
diff --git a/tests/lib/telepathy/contactlist/backend.h b/tests/lib/telepathy/contactlist/backend.h
index 77447d5..024b491 100644
--- a/tests/lib/telepathy/contactlist/backend.h
+++ b/tests/lib/telepathy/contactlist/backend.h
@@ -24,7 +24,7 @@
#include <glib.h>
#include <glib-object.h>
-#include "conn.h"
+#include "contacts-conn.h"
G_BEGIN_DECLS
@@ -61,14 +61,16 @@ TpTestsBackend *tp_tests_backend_new (void);
void tp_tests_backend_set_up (TpTestsBackend *self);
void tp_tests_backend_tear_down (TpTestsBackend *self);
-TpTestsContactListConnection *tp_tests_backend_get_connection (
- TpTestsBackend *self);
+
+TpTestsContactsConnection *tp_tests_backend_get_connection_for_handle (
+ TpTestsBackend *self,
+ gpointer handle);
gpointer tp_tests_backend_add_account (TpTestsBackend *self,
- const gchar *protocol_name,
+ const gchar *protocol,
const gchar *user_id,
- const gchar *connection_manager_name,
- const gchar *account_name);
+ const gchar *cm_name,
+ const gchar *account);
void tp_tests_backend_remove_account (TpTestsBackend *self,
gpointer handle);
diff --git a/tests/lib/telepathy/contactlist/contact-list-manager.c b/tests/lib/telepathy/contactlist/contact-list-manager.c
index b8f19e8..0b78281 100644
--- a/tests/lib/telepathy/contactlist/contact-list-manager.c
+++ b/tests/lib/telepathy/contactlist/contact-list-manager.c
@@ -1,8 +1,8 @@
/*
* Example channel manager for contact lists
*
- * Copyright  2007-2009 Collabora Ltd. <http://www.collabora.co.uk/>
- * Copyright  2007-2009 Nokia Corporation
+ * Copyright  2007-2010 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright  2007-2010 Nokia Corporation
*
* Copying and distribution of this file, with or without modification,
* are permitted in any medium without royalty provided the copyright
@@ -14,130 +14,90 @@
#include "contact-list-manager.h"
#include <string.h>
-
-#include <dbus/dbus-glib.h>
-
#include <telepathy-glib/telepathy-glib.h>
-#include "contact-list.h"
+struct _TpTestsContactListManagerPrivate
+{
+ TpBaseConnection *conn;
-/* elements 0, 1... of this array must be kept in sync with elements 1, 2...
- * of the enum TpTestsContactList in contact-list-manager.h */
-static const gchar *_contact_lists[NUM_TP_TESTS_CONTACT_LISTS + 1] = {
- "subscribe",
- "publish",
- "stored",
- NULL
-};
+ gulong status_changed_id;
-const gchar **
-tp_tests_contact_lists (void)
-{
- return _contact_lists;
-}
+ /* TpHandle => ContactDetails */
+ GHashTable *contact_details;
-/* this array must be kept in sync with the enum
- * TpTestsContactListPresence in contact-list-manager.h */
-static const TpPresenceStatusSpec _statuses[] = {
- { "offline", TP_CONNECTION_PRESENCE_TYPE_OFFLINE, FALSE, NULL },
- { "unknown", TP_CONNECTION_PRESENCE_TYPE_UNKNOWN, FALSE, NULL },
- { "error", TP_CONNECTION_PRESENCE_TYPE_ERROR, FALSE, NULL },
- { "away", TP_CONNECTION_PRESENCE_TYPE_AWAY, TRUE, NULL },
- { "available", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE, TRUE, NULL },
- { NULL }
+ TpHandleRepoIface *contact_repo;
+ TpHandleRepoIface *group_repo;
+ TpHandleSet *groups;
};
-const TpPresenceStatusSpec *
-tp_tests_contact_list_presence_statuses (void)
-{
- return _statuses;
-}
+static void contact_groups_iface_init (TpContactGroupListInterface *iface);
+static void mutable_contact_groups_iface_init (
+ TpMutableContactGroupListInterface *iface);
+static void mutable_iface_init (
+ TpMutableContactListInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (TpTestsContactListManager, tp_tests_contact_list_manager,
+ TP_TYPE_BASE_CONTACT_LIST,
+ G_IMPLEMENT_INTERFACE (TP_TYPE_CONTACT_GROUP_LIST,
+ contact_groups_iface_init);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_MUTABLE_CONTACT_GROUP_LIST,
+ mutable_contact_groups_iface_init)
+ G_IMPLEMENT_INTERFACE (TP_TYPE_MUTABLE_CONTACT_LIST,
+ mutable_iface_init))
typedef struct {
- gchar *id;
- gchar *alias;
+ TpSubscriptionState subscribe;
+ TpSubscriptionState publish;
+ gchar *publish_request;
+ TpHandleSet *groups;
- guint subscribe:1;
- guint publish:1;
- guint subscribe_requested:1;
- guint publish_requested:1;
-
- TpHandleSet *tags;
-
- GPtrArray *contact_info;
-} TpTestsContactDetails;
-
-static TpTestsContactDetails *
-tp_tests_contact_details_new (void)
-{
- return g_slice_new0 (TpTestsContactDetails);
-}
+ TpHandle handle;
+ TpHandleRepoIface *contact_repo;
+} ContactDetails;
static void
-tp_tests_contact_details_destroy (gpointer p)
+contact_detail_destroy (gpointer p)
{
- TpTestsContactDetails *d = p;
+ ContactDetails *d = p;
- if (d->tags != NULL)
- tp_handle_set_destroy (d->tags);
+ g_free (d->publish_request);
+ tp_handle_set_destroy (d->groups);
+ tp_handle_unref (d->contact_repo, d->handle);
- if (d->contact_info != NULL)
- g_ptr_array_unref (d->contact_info);
-
- g_free (d->id);
- g_free (d->alias);
- g_slice_free (TpTestsContactDetails, d);
+ g_slice_free (ContactDetails, d);
}
-static void channel_manager_iface_init (gpointer, gpointer);
-
-G_DEFINE_TYPE_WITH_CODE (TpTestsContactListManager,
- tp_tests_contact_list_manager,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER,
- channel_manager_iface_init))
-
-enum
-{
- ALIAS_UPDATED,
- PRESENCE_UPDATED,
- CONTACT_INFO_UPDATED,
- N_SIGNALS
-};
-
-static guint signals[N_SIGNALS] = { 0 };
-
-enum
+static ContactDetails *
+lookup_contact (TpTestsContactListManager *self,
+ TpHandle handle)
{
- PROP_CONNECTION = 1,
- PROP_SIMULATION_DELAY,
- N_PROPS
-};
+ return g_hash_table_lookup (self->priv->contact_details,
+ GUINT_TO_POINTER (handle));
+}
-struct _TpTestsContactListManagerPrivate
+static ContactDetails *
+ensure_contact (TpTestsContactListManager *self,
+ TpHandle handle)
{
- TpBaseConnection *conn;
- guint simulation_delay;
- TpHandleRepoIface *contact_repo;
- TpHandleRepoIface *group_repo;
+ ContactDetails *d = lookup_contact (self, handle);
- TpHandleSet *contacts;
- /* GUINT_TO_POINTER (handle borrowed from contacts)
- * => TpTestsContactDetails */
- GHashTable *contact_details;
-
- TpTestsContactList *lists[NUM_TP_TESTS_CONTACT_LISTS];
-
- /* GUINT_TO_POINTER (handle borrowed from channel) => TpTestsContactGroup */
- GHashTable *groups;
+ if (d == NULL)
+ {
+ d = g_slice_new0 (ContactDetails);
+ d->subscribe = TP_SUBSCRIPTION_STATE_NO;
+ d->publish = TP_SUBSCRIPTION_STATE_NO;
+ d->publish_request = NULL;
+ d->groups = tp_handle_set_new (self->priv->group_repo);
+ d->handle = handle;
+ d->contact_repo = self->priv->contact_repo;
+ tp_handle_ref (d->contact_repo, d->handle);
- /* borrowed TpExportableChannel => GSList of gpointer (request tokens) that
- * will be satisfied by that channel when the contact list has been
- * downloaded. The requests are in reverse chronological order */
- GHashTable *queued_requests;
+ g_hash_table_insert (self->priv->contact_details,
+ GUINT_TO_POINTER (handle), d);
+ }
- gulong status_changed_id;
-};
+ return d;
+}
static void
tp_tests_contact_list_manager_init (TpTestsContactListManager *self)
@@ -146,94 +106,20 @@ tp_tests_contact_list_manager_init (TpTestsContactListManager *self)
TP_TESTS_TYPE_CONTACT_LIST_MANAGER, TpTestsContactListManagerPrivate);
self->priv->contact_details = g_hash_table_new_full (g_direct_hash,
- g_direct_equal, NULL, tp_tests_contact_details_destroy);
- self->priv->groups = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, g_object_unref);
- self->priv->queued_requests = g_hash_table_new_full (g_direct_hash,
- g_direct_equal, NULL, NULL);
-
- /* initialized properly in constructed() */
- self->priv->contact_repo = NULL;
- self->priv->group_repo = NULL;
- self->priv->contacts = NULL;
+ g_direct_equal, NULL, contact_detail_destroy);
}
static void
-tp_tests_contact_list_manager_close_all (TpTestsContactListManager *self)
+close_all (TpTestsContactListManager *self)
{
- guint i;
-
- if (self->priv->queued_requests != NULL)
- {
- GHashTable *tmp = self->priv->queued_requests;
- GHashTableIter iter;
- gpointer key, value;
-
- self->priv->queued_requests = NULL;
- g_hash_table_iter_init (&iter, tmp);
-
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- GSList *requests = value;
- GSList *l;
-
- requests = g_slist_reverse (requests);
-
- for (l = requests; l != NULL; l = l->next)
- {
- tp_channel_manager_emit_request_failed (self,
- l->data, TP_ERRORS, TP_ERROR_DISCONNECTED,
- "Unable to complete channel request due to disconnection");
- }
-
- g_slist_free (requests);
- g_hash_table_iter_steal (&iter);
- }
-
- g_hash_table_destroy (tmp);
- }
-
- if (self->priv->contacts != NULL)
- {
- tp_handle_set_destroy (self->priv->contacts);
- self->priv->contacts = NULL;
- }
-
- if (self->priv->contact_details != NULL)
- {
- GHashTable *tmp = self->priv->contact_details;
-
- self->priv->contact_details = NULL;
- g_hash_table_destroy (tmp);
- }
-
- if (self->priv->groups != NULL)
- {
- GHashTable *tmp = self->priv->groups;
-
- self->priv->groups = NULL;
- g_hash_table_destroy (tmp);
- }
-
- for (i = 0; i < NUM_TP_TESTS_CONTACT_LISTS; i++)
- {
- if (self->priv->lists[i] != NULL)
- {
- TpTestsContactList *list = self->priv->lists[i];
-
- /* set self->priv->lists[i] to NULL here so list_closed_cb does
- * not try to delete the list again */
- self->priv->lists[i] = NULL;
- g_object_unref (list);
- }
- }
-
if (self->priv->status_changed_id != 0)
{
g_signal_handler_disconnect (self->priv->conn,
self->priv->status_changed_id);
self->priv->status_changed_id = 0;
}
+ tp_clear_pointer (&self->priv->contact_details, g_hash_table_unref);
+ tp_clear_pointer (&self->priv->groups, tp_handle_set_destroy);
}
static void
@@ -241,1051 +127,536 @@ dispose (GObject *object)
{
TpTestsContactListManager *self = TP_TESTS_CONTACT_LIST_MANAGER (object);
- tp_tests_contact_list_manager_close_all (self);
- g_assert (self->priv->groups == NULL);
- g_assert (self->priv->lists[0] == NULL);
- g_assert (self->priv->queued_requests == NULL);
+ close_all (self);
((GObjectClass *) tp_tests_contact_list_manager_parent_class)->dispose (
object);
}
-static void
-get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
+static TpHandleSet *
+contact_list_dup_contacts (TpBaseContactList *base)
{
- TpTestsContactListManager *self = TP_TESTS_CONTACT_LIST_MANAGER (object);
+ TpTestsContactListManager *self = TP_TESTS_CONTACT_LIST_MANAGER (base);
+ TpHandleSet *set;
+ GHashTableIter iter;
+ gpointer k, v;
- switch (property_id)
- {
- case PROP_CONNECTION:
- g_value_set_object (value, self->priv->conn);
- break;
+ set = tp_handle_set_new (self->priv->contact_repo);
- case PROP_SIMULATION_DELAY:
- g_value_set_uint (value, self->priv->simulation_delay);
- break;
+ g_hash_table_iter_init (&iter, self->priv->contact_details);
+ while (g_hash_table_iter_next (&iter, &k, &v))
+ {
+ ContactDetails *d = v;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ /* add all the interesting items */
+ if (d->subscribe != TP_SUBSCRIPTION_STATE_NO ||
+ d->publish != TP_SUBSCRIPTION_STATE_NO)
+ tp_handle_set_add (set, GPOINTER_TO_UINT (k));
}
+
+ return set;
}
static void
-set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
+contact_list_dup_states (TpBaseContactList *base,
+ TpHandle contact,
+ TpSubscriptionState *subscribe,
+ TpSubscriptionState *publish,
+ gchar **publish_request)
{
- TpTestsContactListManager *self = TP_TESTS_CONTACT_LIST_MANAGER (object);
+ TpTestsContactListManager *self = TP_TESTS_CONTACT_LIST_MANAGER (base);
+ ContactDetails *d = lookup_contact (self, contact);
- switch (property_id)
+ if (d == NULL)
{
- case PROP_CONNECTION:
- /* We don't ref the connection, because it owns a reference to the
- * manager, and it guarantees that the manager's lifetime is
- * less than its lifetime */
- self->priv->conn = g_value_get_object (value);
- break;
+ if (subscribe != NULL)
+ *subscribe = TP_SUBSCRIPTION_STATE_NO;
- case PROP_SIMULATION_DELAY:
- self->priv->simulation_delay = g_value_get_uint (value);
- break;
+ if (publish != NULL)
+ *publish = TP_SUBSCRIPTION_STATE_NO;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ if (publish_request != NULL)
+ *publish_request = NULL;
}
-}
+ else
+ {
+ if (subscribe != NULL)
+ *subscribe = d->subscribe;
-static void
-satisfy_queued_requests (TpExportableChannel *channel,
- gpointer user_data)
-{
- TpTestsContactListManager *self = TP_TESTS_CONTACT_LIST_MANAGER (user_data);
- GSList *requests = g_hash_table_lookup (self->priv->queued_requests,
- channel);
-
- /* this is all fine even if requests is NULL */
- g_hash_table_steal (self->priv->queued_requests, channel);
- requests = g_slist_reverse (requests);
- tp_channel_manager_emit_new_channel (self, channel, requests);
- g_slist_free (requests);
-}
+ if (publish != NULL)
+ *publish = d->publish;
-static TpTestsContactDetails *
-lookup_contact (TpTestsContactListManager *self,
- TpHandle contact)
-{
- return g_hash_table_lookup (self->priv->contact_details,
- GUINT_TO_POINTER (contact));
+ if (publish_request != NULL)
+ *publish_request = g_strdup (d->publish_request);
+ }
}
-static TpTestsContactDetails *
-ensure_contact (TpTestsContactListManager *self,
- TpHandle contact,
- gboolean *created)
+static GStrv
+contact_list_dup_groups (TpBaseContactList *base)
{
- TpTestsContactDetails *ret = lookup_contact (self, contact);
+ TpTestsContactListManager *self = TP_TESTS_CONTACT_LIST_MANAGER (base);
+ GPtrArray *ret;
- if (ret == NULL)
+ if (self->priv->groups != NULL)
{
- tp_handle_set_add (self->priv->contacts, contact);
+ TpIntSetFastIter iter;
+ TpHandle group;
- ret = tp_tests_contact_details_new ();
- ret->alias = g_strdup (tp_handle_inspect (self->priv->contact_repo,
- contact));
+ ret = g_ptr_array_sized_new (tp_handle_set_size (self->priv->groups) + 1);
- g_hash_table_insert (self->priv->contact_details,
- GUINT_TO_POINTER (contact), ret);
-
- if (created != NULL)
- *created = TRUE;
+ tp_intset_fast_iter_init (&iter, tp_handle_set_peek (self->priv->groups));
+ while (tp_intset_fast_iter_next (&iter, &group))
+ {
+ g_ptr_array_add (ret, g_strdup (tp_handle_inspect (
+ self->priv->group_repo, group)));
+ }
}
- else if (created != NULL)
+ else
{
- *created = FALSE;
+ ret = g_ptr_array_sized_new (1);
}
- return ret;
+ g_ptr_array_add (ret, NULL);
+
+ return (GStrv) g_ptr_array_free (ret, FALSE);
}
-static void
-tp_tests_contact_list_manager_foreach_channel (TpChannelManager *manager,
- TpExportableChannelFunc callback,
- gpointer user_data)
+static GStrv
+contact_list_dup_contact_groups (TpBaseContactList *base,
+ TpHandle contact)
{
- TpTestsContactListManager *self = TP_TESTS_CONTACT_LIST_MANAGER (manager);
- GHashTableIter iter;
- gpointer handle, channel;
- guint i;
+ TpTestsContactListManager *self = TP_TESTS_CONTACT_LIST_MANAGER (base);
+ ContactDetails *d = lookup_contact (self, contact);
+ GPtrArray *ret;
- for (i = 0; i < NUM_TP_TESTS_CONTACT_LISTS; i++)
+ if (d != NULL && d->groups != NULL)
{
- if (self->priv->lists[i] != NULL)
- callback (TP_EXPORTABLE_CHANNEL (self->priv->lists[i]), user_data);
- }
+ TpIntSetFastIter iter;
+ TpHandle group;
- g_hash_table_iter_init (&iter, self->priv->groups);
+ ret = g_ptr_array_sized_new (tp_handle_set_size (d->groups) + 1);
- while (g_hash_table_iter_next (&iter, &handle, &channel))
+ tp_intset_fast_iter_init (&iter, tp_handle_set_peek (d->groups));
+ while (tp_intset_fast_iter_next (&iter, &group))
+ {
+ g_ptr_array_add (ret, g_strdup (tp_handle_inspect (
+ self->priv->group_repo, group)));
+ }
+ }
+ else
{
- callback (TP_EXPORTABLE_CHANNEL (channel), user_data);
+ ret = g_ptr_array_sized_new (1);
}
-}
-
-static TpTestsContactGroup *ensure_group (TpTestsContactListManager *self,
- TpHandle handle);
-
-static TpTestsContactList *ensure_list (TpTestsContactListManager *self,
- TpTestsContactListHandle handle);
-
-/*
- * _insert_contact_field:
- * @contact_info: an array of Contact_Info_Field structures
- * @field_name: a vCard field name in any case combination
- * @field_params: a list of vCard type-parameters, typically of the form
- * type=xxx; must be in lower-case if case-insensitive
- * @field_values: for unstructured fields, an array containing one element;
- * for structured fields, the elements of the field in order
- */
-static void
-_insert_contact_field (GPtrArray *contact_info,
- const gchar *field_name,
- const gchar * const *field_params,
- const gchar * const *field_values)
-{
- const gchar * const *empty_strv = { NULL };
- gchar *field_name_down = g_ascii_strdown (field_name, -1);
-
- if (field_params == NULL)
- field_params = empty_strv;
- if (field_values == NULL)
- field_values = empty_strv;
- g_ptr_array_add (contact_info, tp_value_array_build (3,
- G_TYPE_STRING, field_name_down,
- G_TYPE_STRV, field_params,
- G_TYPE_STRV, field_values,
- G_TYPE_INVALID));
+ g_ptr_array_add (ret, NULL);
- g_free (field_name_down);
+ return (GStrv) g_ptr_array_free (ret, FALSE);
}
-static gboolean
-receive_contact_lists (gpointer p)
+static TpHandleSet *
+contact_list_dup_group_members (TpBaseContactList *base,
+ const gchar *group)
{
- TpTestsContactListManager *self = p;
- TpHandle handle, cambridge, montreal, francophones;
- const gchar *id;
- TpTestsContactDetails *d;
- TpIntSet *set, *cam_set, *mtl_set, *fr_set;
- TpIntSetFastIter iter;
- TpTestsContactList *subscribe, *publish, *stored;
- TpTestsContactGroup *cambridge_group, *montreal_group,
- *francophones_group;
+ TpTestsContactListManager *self = TP_TESTS_CONTACT_LIST_MANAGER (base);
+ TpHandleSet *set;
+ TpHandle group_handle;
+ GHashTableIter iter;
+ gpointer k, v;
- if (self->priv->groups == NULL)
+ set = tp_handle_set_new (self->priv->contact_repo);
+ group_handle = tp_handle_lookup (self->priv->group_repo, group, NULL, NULL);
+ if (G_UNLIKELY (group_handle == 0))
{
- /* connection already disconnected, so don't process the
- * "data from the server" */
- return FALSE;
+ /* clearly it doesn't have members */
+ return set;
}
- /* In a real CM we'd have received a contact list from the server at this
- * point. But this isn't a real CM, so we have to make one up... */
+ g_hash_table_iter_init (&iter, self->priv->contact_details);
+ while (g_hash_table_iter_next (&iter, &k, &v))
+ {
+ ContactDetails *d = v;
- subscribe = ensure_list (self, TP_TESTS_CONTACT_LIST_SUBSCRIBE);
- publish = ensure_list (self, TP_TESTS_CONTACT_LIST_PUBLISH);
- stored = ensure_list (self, TP_TESTS_CONTACT_LIST_STORED);
+ if (d->groups != NULL &&
+ tp_handle_set_is_member (d->groups, group_handle))
+ tp_handle_set_add (set, GPOINTER_TO_UINT (k));
+ }
- cambridge = tp_handle_ensure (self->priv->group_repo, "Cambridge", NULL,
- NULL);
- montreal = tp_handle_ensure (self->priv->group_repo, "Montreal", NULL,
- NULL);
- francophones = tp_handle_ensure (self->priv->group_repo, "Francophones",
- NULL, NULL);
+ return set;
+}
- cambridge_group = ensure_group (self, cambridge);
- montreal_group = ensure_group (self, montreal);
- francophones_group = ensure_group (self, francophones);
+static void
+contact_list_set_contact_groups_async (TpBaseContactList *base,
+ TpHandle contact,
+ const gchar * const *names,
+ gsize n,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ TpTestsContactListManager *self = TP_TESTS_CONTACT_LIST_MANAGER (base);
+ ContactDetails *d;
+ TpIntset *set, *added_set, *removed_set;
+ GPtrArray *added_names, *removed_names;
+ GPtrArray *new_groups;
+ TpIntSetFastIter iter;
+ TpHandle group_handle;
+ guint i;
- /* Add various people who are already subscribing and publishing */
+ d = ensure_contact (self, contact);
+ new_groups = g_ptr_array_new ();
set = tp_intset_new ();
- cam_set = tp_intset_new ();
- mtl_set = tp_intset_new ();
- fr_set = tp_intset_new ();
-
- id = "sjoerd example com";
- handle = tp_handle_ensure (self->priv->contact_repo, id, NULL, NULL);
- tp_intset_add (set, handle);
- tp_intset_add (cam_set, handle);
- d = ensure_contact (self, handle, NULL);
- g_free (d->id);
- d->id = g_strdup (id);
- g_free (d->alias);
- d->alias = g_strdup ("Sjoerd");
- d->subscribe = TRUE;
- d->publish = TRUE;
- d->tags = tp_handle_set_new (self->priv->group_repo);
- tp_handle_set_add (d->tags, cambridge);
- d->contact_info = dbus_g_type_specialized_construct (
- TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST);
- {
- const gchar * values[] = { "+14401223357708", NULL };
- _insert_contact_field (d->contact_info, "tel", NULL,
- (const gchar * const *) values);
- }
- tp_handle_unref (self->priv->contact_repo, handle);
-
- id = "guillaume example com";
- handle = tp_handle_ensure (self->priv->contact_repo, id, NULL, NULL);
- tp_intset_add (set, handle);
- tp_intset_add (cam_set, handle);
- tp_intset_add (fr_set, handle);
- d = ensure_contact (self, handle, NULL);
- g_free (d->id);
- d->id = g_strdup (id);
- g_free (d->alias);
- d->alias = g_strdup ("Guillaume");
- d->subscribe = TRUE;
- d->publish = TRUE;
- d->tags = tp_handle_set_new (self->priv->group_repo);
- tp_handle_set_add (d->tags, cambridge);
- tp_handle_set_add (d->tags, francophones);
- tp_handle_unref (self->priv->contact_repo, handle);
-
- id = "olivier example com";
- handle = tp_handle_ensure (self->priv->contact_repo, id, NULL, NULL);
- tp_intset_add (set, handle);
- tp_intset_add (mtl_set, handle);
- tp_intset_add (fr_set, handle);
- d = ensure_contact (self, handle, NULL);
- g_free (d->id);
- d->id = g_strdup (id);
- g_free (d->alias);
- d->alias = g_strdup ("Olivier");
- d->subscribe = TRUE;
- d->publish = TRUE;
- d->tags = tp_handle_set_new (self->priv->group_repo);
- tp_handle_set_add (d->tags, montreal);
- tp_handle_set_add (d->tags, francophones);
- d->contact_info = dbus_g_type_specialized_construct (
- TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST);
- {
- const gchar * values[] = { "+15142345678", NULL };
- _insert_contact_field (d->contact_info, "tel", NULL,
- (const gchar * const *) values);
- }
- {
- const gchar * values[] = { "1982-01-02T13:57Z", NULL };
- _insert_contact_field (d->contact_info, "tel", NULL,
- (const gchar * const *) values);
- }
- {
- const gchar * values[] = { "Olivier Crete", NULL };
- _insert_contact_field (d->contact_info, "fn", NULL,
- (const gchar * const *) values);
- }
- {
- const gchar * values[] = { id, NULL };
- _insert_contact_field (d->contact_info, "email", NULL,
- (const gchar * const *) values);
- }
- {
- const gchar * values[] = { "ocrete.example.com", NULL };
- _insert_contact_field (d->contact_info, "url", NULL,
- (const gchar * const *) values);
- }
- tp_handle_unref (self->priv->contact_repo, handle);
-
- id = "travis example com";
- handle = tp_handle_ensure (self->priv->contact_repo, id, NULL, NULL);
- tp_intset_add (set, handle);
- d = ensure_contact (self, handle, NULL);
- g_free (d->id);
- d->id = g_strdup (id);
- g_free (d->alias);
- d->alias = g_strdup ("Travis");
- d->subscribe = TRUE;
- d->publish = TRUE;
- tp_handle_unref (self->priv->contact_repo, handle);
-
- tp_group_mixin_change_members ((GObject *) subscribe, "",
- set, NULL, NULL, NULL,
- 0, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_group_mixin_change_members ((GObject *) publish, "",
- set, NULL, NULL, NULL,
- 0, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_group_mixin_change_members ((GObject *) stored, "",
- set, NULL, NULL, NULL,
- 0, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
-
- tp_intset_fast_iter_init (&iter, set);
-
- while (tp_intset_fast_iter_next (&iter, &handle))
+ for (i = 0; i < n; i++)
{
- g_signal_emit (self, signals[ALIAS_UPDATED], 0, handle);
- g_signal_emit (self, signals[PRESENCE_UPDATED], 0, handle);
- g_signal_emit (self, signals[CONTACT_INFO_UPDATED], 0, handle);
- }
+ group_handle = tp_handle_ensure (self->priv->group_repo, names[i], NULL, NULL);
+ tp_intset_add (set, group_handle);
- tp_intset_destroy (set);
-
- /* Add a couple of people whose presence we've requested. They are
- * remote-pending in subscribe */
+ if (!tp_handle_set_is_member (self->priv->groups, group_handle))
+ {
+ tp_handle_set_add (self->priv->groups, group_handle);
+ g_ptr_array_add (new_groups, (gchar *) names[i]);
+ }
+ }
- set = tp_intset_new ();
+ if (new_groups->len > 0)
+ {
+ tp_base_contact_list_groups_created ((TpBaseContactList *) self,
+ (const gchar * const *) new_groups->pdata, new_groups->len);
+ }
- id = "geraldine example com";
- handle = tp_handle_ensure (self->priv->contact_repo, id, NULL, NULL);
- tp_intset_add (set, handle);
- tp_intset_add (cam_set, handle);
- tp_intset_add (fr_set, handle);
- d = ensure_contact (self, handle, NULL);
- g_free (d->id);
- d->id = g_strdup (id);
- g_free (d->alias);
- d->alias = g_strdup ("GÃraldine");
- d->subscribe_requested = TRUE;
- d->tags = tp_handle_set_new (self->priv->group_repo);
- tp_handle_set_add (d->tags, cambridge);
- tp_handle_set_add (d->tags, francophones);
- tp_handle_unref (self->priv->contact_repo, handle);
-
- id = "helen example com";
- handle = tp_handle_ensure (self->priv->contact_repo, id, NULL, NULL);
- tp_intset_add (set, handle);
- tp_intset_add (cam_set, handle);
- d = ensure_contact (self, handle, NULL);
- g_free (d->id);
- d->id = g_strdup (id);
- g_free (d->alias);
- d->alias = g_strdup ("Helen");
- d->subscribe_requested = TRUE;
- d->tags = tp_handle_set_new (self->priv->group_repo);
- tp_handle_set_add (d->tags, cambridge);
- tp_handle_unref (self->priv->contact_repo, handle);
-
- tp_group_mixin_change_members ((GObject *) subscribe, "",
- NULL, NULL, NULL, set,
- 0, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_group_mixin_change_members ((GObject *) stored, "",
- set, NULL, NULL, NULL,
- 0, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
-
- tp_intset_fast_iter_init (&iter, set);
-
- while (tp_intset_fast_iter_next (&iter, &handle))
+ added_set = tp_intset_difference (set, tp_handle_set_peek (d->groups));
+ added_names = g_ptr_array_sized_new (tp_intset_size (added_set));
+ tp_intset_fast_iter_init (&iter, added_set);
+ while (tp_intset_fast_iter_next (&iter, &group_handle))
{
- g_signal_emit (self, signals[ALIAS_UPDATED], 0, handle);
- g_signal_emit (self, signals[PRESENCE_UPDATED], 0, handle);
- g_signal_emit (self, signals[CONTACT_INFO_UPDATED], 0, handle);
+ g_ptr_array_add (added_names, (gchar *) tp_handle_inspect (
+ self->priv->group_repo, group_handle));
}
+ tp_intset_destroy (added_set);
- tp_intset_destroy (set);
+ removed_set = tp_intset_difference (tp_handle_set_peek (d->groups), set);
+ removed_names = g_ptr_array_sized_new (tp_intset_size (removed_set));
+ tp_intset_fast_iter_init (&iter, removed_set);
+ while (tp_intset_fast_iter_next (&iter, &group_handle))
+ {
+ g_ptr_array_add (removed_names, (gchar *) tp_handle_inspect (
+ self->priv->group_repo, group_handle));
+ }
+ tp_intset_destroy (removed_set);
- /* Receive a couple of authorization requests too. These people are
- * local-pending in publish */
-
- id = "wim example com";
- handle = tp_handle_ensure (self->priv->contact_repo, id, NULL, NULL);
- d = ensure_contact (self, handle, NULL);
- g_free (d->id);
- d->id = g_strdup (id);
- g_free (d->alias);
- d->alias = g_strdup ("Wim");
- d->publish_requested = TRUE;
- tp_handle_unref (self->priv->contact_repo, handle);
-
- set = tp_intset_new_containing (handle);
- tp_group_mixin_change_members ((GObject *) publish,
- "I'm more metal than you!",
- NULL, NULL, set, NULL,
- handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_group_mixin_change_members ((GObject *) stored, "",
- set, NULL, NULL, NULL,
- handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (set);
- g_signal_emit (self, signals[ALIAS_UPDATED], 0, handle);
- g_signal_emit (self, signals[PRESENCE_UPDATED], 0, handle);
- g_signal_emit (self, signals[CONTACT_INFO_UPDATED], 0, handle);
-
- id = "christian example com";
- handle = tp_handle_ensure (self->priv->contact_repo, id, NULL, NULL);
- d = ensure_contact (self, handle, NULL);
- g_free (d->id);
- d->id = g_strdup (id);
- g_free (d->alias);
- d->alias = g_strdup ("Christian");
- d->publish_requested = TRUE;
- tp_handle_unref (self->priv->contact_repo, handle);
-
- set = tp_intset_new_containing (handle);
- tp_group_mixin_change_members ((GObject *) publish,
- "I have some fermented herring for you",
- NULL, NULL, set, NULL,
- handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_group_mixin_change_members ((GObject *) stored, "",
- set, NULL, NULL, NULL,
- handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
+ tp_handle_set_destroy (d->groups);
+ d->groups = tp_handle_set_new_from_intset (self->priv->group_repo, set);
tp_intset_destroy (set);
- g_signal_emit (self, signals[ALIAS_UPDATED], 0, handle);
- g_signal_emit (self, signals[PRESENCE_UPDATED], 0, handle);
- g_signal_emit (self, signals[CONTACT_INFO_UPDATED], 0, handle);
-
- tp_group_mixin_change_members ((GObject *) cambridge_group, "",
- cam_set, NULL, NULL, NULL,
- 0, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_group_mixin_change_members ((GObject *) montreal_group, "",
- mtl_set, NULL, NULL, NULL,
- 0, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_group_mixin_change_members ((GObject *) francophones_group, "",
- fr_set, NULL, NULL, NULL,
- 0, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
-
- tp_intset_destroy (fr_set);
- tp_intset_destroy (cam_set);
- tp_intset_destroy (mtl_set);
- tp_handle_unref (self->priv->group_repo, cambridge);
- tp_handle_unref (self->priv->group_repo, montreal);
- tp_handle_unref (self->priv->group_repo, francophones);
-
- /* Now we've received the roster, we can satisfy all the queued requests */
-
- tp_tests_contact_list_manager_foreach_channel ((TpChannelManager *) self,
- satisfy_queued_requests, self);
+ if (added_names->len > 0 || removed_names->len > 0)
+ {
+ tp_base_contact_list_one_contact_groups_changed (base, contact,
+ (const gchar * const *) added_names->pdata, added_names->len,
+ (const gchar * const *) removed_names->pdata, removed_names->len);
+ }
- g_assert (g_hash_table_size (self->priv->queued_requests) == 0);
- g_hash_table_destroy (self->priv->queued_requests);
- self->priv->queued_requests = NULL;
+ tp_simple_async_report_success_in_idle ((GObject *) self, callback,
+ user_data, contact_list_set_contact_groups_async);
- return FALSE;
+ g_ptr_array_unref (added_names);
+ g_ptr_array_unref (removed_names);
+ g_ptr_array_unref (new_groups);
}
static void
-status_changed_cb (TpBaseConnection *conn,
- guint status,
- guint reason,
- TpTestsContactListManager *self)
+contact_list_set_group_members_async (TpBaseContactList *base,
+ const gchar *normalized_group,
+ TpHandleSet *contacts,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- switch (status)
- {
- case TP_CONNECTION_STATUS_CONNECTED:
- {
- /* Do network I/O to get the contact list. This connection manager
- * doesn't really have a server, so simulate a small network delay
- * then invent a contact list */
- g_timeout_add_full (G_PRIORITY_DEFAULT,
- 2 * self->priv->simulation_delay, receive_contact_lists,
- g_object_ref (self), g_object_unref);
- }
- break;
+ GSimpleAsyncResult *simple;
- case TP_CONNECTION_STATUS_CONNECTING:
- /* nothing to do here */
- break;
-
- case TP_CONNECTION_STATUS_DISCONNECTED:
- {
- tp_tests_contact_list_manager_close_all (self);
- }
- break;
- default:
- g_assert_not_reached ();
- }
+ simple = g_simple_async_result_new_error ((GObject *) base, callback,
+ user_data, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Not implemented");
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
}
static void
-constructed (GObject *object)
+contact_list_add_to_group_async (TpBaseContactList *base,
+ const gchar *group,
+ TpHandleSet *contacts,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- TpTestsContactListManager *self = TP_TESTS_CONTACT_LIST_MANAGER (object);
- void (*chain_up) (GObject *) =
- ((GObjectClass *) tp_tests_contact_list_manager_parent_class)->constructed;
-
- if (chain_up != NULL)
- {
- chain_up (object);
- }
-
- self->priv->contact_repo = tp_base_connection_get_handles (self->priv->conn,
- TP_HANDLE_TYPE_CONTACT);
- self->priv->group_repo = tp_base_connection_get_handles (self->priv->conn,
- TP_HANDLE_TYPE_GROUP);
- self->priv->contacts = tp_handle_set_new (self->priv->contact_repo);
+ GSimpleAsyncResult *simple;
- self->priv->status_changed_id = g_signal_connect (self->priv->conn,
- "status-changed", (GCallback) status_changed_cb, self);
+ simple = g_simple_async_result_new_error ((GObject *) base, callback,
+ user_data, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Not implemented");
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
}
static void
-tp_tests_contact_list_manager_class_init (TpTestsContactListManagerClass *klass)
+contact_list_remove_from_group_async (TpBaseContactList *base,
+ const gchar *group,
+ TpHandleSet *contacts,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- GParamSpec *param_spec;
- GObjectClass *object_class = (GObjectClass *) klass;
-
- object_class->constructed = constructed;
- object_class->dispose = dispose;
- object_class->get_property = get_property;
- object_class->set_property = set_property;
-
- param_spec = g_param_spec_object ("connection", "Connection object",
- "The connection that owns this channel manager",
- TP_TYPE_BASE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
- param_spec = g_param_spec_uint ("simulation-delay", "Simulation delay",
- "Delay between simulated network events",
- 0, G_MAXUINT32, 1000,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_SIMULATION_DELAY,
- param_spec);
-
- g_type_class_add_private (klass, sizeof (TpTestsContactListManagerPrivate));
+ GSimpleAsyncResult *simple;
- signals[ALIAS_UPDATED] = g_signal_new ("alias-updated",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT);
-
- signals[PRESENCE_UPDATED] = g_signal_new ("presence-updated",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT);
-
- signals[CONTACT_INFO_UPDATED] = g_signal_new ("contact-info-updated",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT);
+ simple = g_simple_async_result_new_error ((GObject *) base, callback,
+ user_data, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Not implemented");
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
}
static void
-list_closed_cb (TpTestsContactList *chan,
- TpTestsContactListManager *self)
+contact_list_remove_group_async (TpBaseContactList *base,
+ const gchar *group,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- TpHandle handle;
-
- tp_channel_manager_emit_channel_closed_for_object (self,
- TP_EXPORTABLE_CHANNEL (chan));
+ GSimpleAsyncResult *simple;
- g_object_get (chan,
- "handle", &handle,
- NULL);
-
- if (self->priv->lists[handle] == NULL)
- return;
-
- g_assert (chan == self->priv->lists[handle]);
- g_object_unref (self->priv->lists[handle]);
- self->priv->lists[handle] = NULL;
+ simple = g_simple_async_result_new_error ((GObject *) base, callback,
+ user_data, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Not implemented");
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
}
static void
-group_closed_cb (TpTestsContactGroup *chan,
- TpTestsContactListManager *self)
+contact_list_request_subscription_async (TpBaseContactList *self,
+ TpHandleSet *contacts,
+ const gchar *message,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- tp_channel_manager_emit_channel_closed_for_object (self,
- TP_EXPORTABLE_CHANNEL (chan));
+ GArray *handles;
- if (self->priv->groups != NULL)
- {
- TpHandle handle;
-
- g_object_get (chan,
- "handle", &handle,
- NULL);
+ handles = tp_handle_set_to_array (contacts);
+ tp_tests_contact_list_manager_request_subscription (
+ (TpTestsContactListManager *) self,
+ handles->len, (TpHandle *) handles->data, message);
+ g_array_unref (handles);
- g_hash_table_remove (self->priv->groups, GUINT_TO_POINTER (handle));
- }
+ tp_simple_async_report_success_in_idle ((GObject *) self, callback,
+ user_data, contact_list_request_subscription_async);
}
-static TpTestsContactListBase *
-new_channel (TpTestsContactListManager *self,
- TpHandleType handle_type,
- TpHandle handle,
- gpointer request_token)
+static void
+contact_list_authorize_publication_async (TpBaseContactList *self,
+ TpHandleSet *contacts,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- TpTestsContactListBase *chan;
- gchar *object_path;
- GType type;
- GSList *requests = NULL;
+ GArray *handles;
- if (handle_type == TP_HANDLE_TYPE_LIST)
- {
- /* Some Telepathy clients wrongly assume that contact lists of type LIST
- * have object paths ending with "/subscribe", "/publish" etc. -
- * telepathy-spec has no such guarantee, so in this tp_test we break
- * those clients. Please read the spec when implementing it :-) */
- object_path = g_strdup_printf ("%s/%sContactList",
- self->priv->conn->object_path, _contact_lists[handle - 1]);
- type = TP_TESTS_TYPE_CONTACT_LIST;
- }
- else
- {
- /* Using Group%u (with handle as the value of %u) would be OK here too,
- * but we'll encode the group name into the object path to be kind
- * to people reading debug logs. */
- gchar *id = tp_escape_as_identifier (tp_handle_inspect (
- self->priv->group_repo, handle));
-
- g_assert (handle_type == TP_HANDLE_TYPE_GROUP);
- object_path = g_strdup_printf ("%s/Group/%s",
- self->priv->conn->object_path, id);
- type = TP_TESTS_TYPE_CONTACT_GROUP;
-
- g_free (id);
- }
-
- chan = g_object_new (type,
- "connection", self->priv->conn,
- "manager", self,
- "object-path", object_path,
- "handle-type", handle_type,
- "handle", handle,
- NULL);
-
- g_free (object_path);
-
- if (handle_type == TP_HANDLE_TYPE_LIST)
- {
- g_signal_connect (chan, "closed", (GCallback) list_closed_cb, self);
- g_assert (self->priv->lists[handle] == NULL);
- self->priv->lists[handle] = TP_TESTS_CONTACT_LIST (chan);
- }
- else
- {
- g_signal_connect (chan, "closed", (GCallback) group_closed_cb, self);
-
- g_assert (g_hash_table_lookup (self->priv->groups,
- GUINT_TO_POINTER (handle)) == NULL);
- g_hash_table_insert (self->priv->groups, GUINT_TO_POINTER (handle),
- TP_TESTS_CONTACT_GROUP (chan));
- }
+ handles = tp_handle_set_to_array (contacts);
+ tp_tests_contact_list_manager_authorize_publication (
+ (TpTestsContactListManager *) self,
+ handles->len, (TpHandle *) handles->data);
+ g_array_unref (handles);
- if (self->priv->queued_requests == NULL)
- {
- if (request_token != NULL)
- requests = g_slist_prepend (requests, request_token);
-
- tp_channel_manager_emit_new_channel (self, TP_EXPORTABLE_CHANNEL (chan),
- requests);
- g_slist_free (requests);
- }
- else if (request_token != NULL)
- {
- /* initial contact list not received yet, so we have to wait for it */
- requests = g_hash_table_lookup (self->priv->queued_requests, chan);
- g_hash_table_steal (self->priv->queued_requests, chan);
- requests = g_slist_prepend (requests, request_token);
- g_hash_table_insert (self->priv->queued_requests, chan, requests);
- }
-
- return chan;
+ tp_simple_async_report_success_in_idle ((GObject *) self, callback,
+ user_data, contact_list_authorize_publication_async);
}
-static TpTestsContactList *
-ensure_list (TpTestsContactListManager *self,
- TpTestsContactListHandle handle)
+static void
+contact_list_remove_contacts_async (TpBaseContactList *self,
+ TpHandleSet *contacts,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- if (self->priv->lists[handle] == NULL)
- {
- new_channel (self, TP_HANDLE_TYPE_LIST, handle, NULL);
- g_assert (self->priv->lists[handle] != NULL);
- }
+ GArray *handles;
+
+ handles = tp_handle_set_to_array (contacts);
+ tp_tests_contact_list_manager_remove (
+ (TpTestsContactListManager *) self,
+ handles->len, (TpHandle *) handles->data);
+ g_array_unref (handles);
- return self->priv->lists[handle];
+ tp_simple_async_report_success_in_idle ((GObject *) self, callback,
+ user_data, contact_list_remove_contacts_async);
}
-static TpTestsContactGroup *
-ensure_group (TpTestsContactListManager *self,
- TpHandle handle)
+static void
+contact_list_unsubscribe_async (TpBaseContactList *self,
+ TpHandleSet *contacts,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- TpTestsContactGroup *group = g_hash_table_lookup (self->priv->groups,
- GUINT_TO_POINTER (handle));
+ GArray *handles;
- if (group == NULL)
- {
- group = TP_TESTS_CONTACT_GROUP (new_channel (self, TP_HANDLE_TYPE_GROUP,
- handle, NULL));
- }
+ handles = tp_handle_set_to_array (contacts);
+ tp_tests_contact_list_manager_unsubscribe (
+ (TpTestsContactListManager *) self,
+ handles->len, (TpHandle *) handles->data);
+ g_array_unref (handles);
- return group;
+ tp_simple_async_report_success_in_idle ((GObject *) self, callback,
+ user_data, contact_list_unsubscribe_async);
}
-static const gchar * const fixed_properties[] = {
- TP_PROP_CHANNEL_CHANNEL_TYPE,
- TP_PROP_CHANNEL_TARGET_HANDLE_TYPE,
- NULL
-};
-
-static const gchar * const allowed_properties[] = {
- TP_PROP_CHANNEL_TARGET_HANDLE,
- TP_PROP_CHANNEL_TARGET_ID,
- NULL
-};
-
static void
-tp_tests_contact_list_manager_foreach_channel_class (TpChannelManager *manager,
- TpChannelManagerChannelClassFunc func,
+contact_list_unpublish_async (TpBaseContactList *self,
+ TpHandleSet *contacts,
+ GAsyncReadyCallback callback,
gpointer user_data)
{
- GHashTable *table = tp_asv_new (
- TP_PROP_CHANNEL_CHANNEL_TYPE,
- G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
- TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_LIST,
- NULL);
-
- func (manager, table, allowed_properties, user_data);
+ GArray *handles;
- g_hash_table_insert (table, (gpointer) TP_PROP_CHANNEL_TARGET_HANDLE_TYPE,
- tp_g_value_slice_new_uint (TP_HANDLE_TYPE_GROUP));
- func (manager, table, allowed_properties, user_data);
+ handles = tp_handle_set_to_array (contacts);
+ tp_tests_contact_list_manager_unpublish (
+ (TpTestsContactListManager *) self,
+ handles->len, (TpHandle *) handles->data);
+ g_array_unref (handles);
- g_hash_table_destroy (table);
+ tp_simple_async_report_success_in_idle ((GObject *) self, callback,
+ user_data, contact_list_unpublish_async);
}
-static gboolean
-tp_tests_contact_list_manager_request (TpTestsContactListManager *self,
- gpointer request_token,
- GHashTable *request_properties,
- gboolean require_new)
+static void
+status_changed_cb (TpBaseConnection *conn,
+ guint status,
+ guint reason,
+ TpTestsContactListManager *self)
{
- TpHandleType handle_type;
- TpHandle handle;
- TpTestsContactListBase *chan;
- GError *error = NULL;
-
- if (tp_strdiff (tp_asv_get_string (request_properties,
- TP_PROP_CHANNEL_CHANNEL_TYPE),
- TP_IFACE_CHANNEL_TYPE_CONTACT_LIST))
- {
- return FALSE;
- }
-
- handle_type = tp_asv_get_uint32 (request_properties,
- TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL);
-
- if (handle_type != TP_HANDLE_TYPE_LIST &&
- handle_type != TP_HANDLE_TYPE_GROUP)
+ switch (status)
{
- return FALSE;
- }
-
- handle = tp_asv_get_uint32 (request_properties,
- TP_PROP_CHANNEL_TARGET_HANDLE, NULL);
- g_assert (handle != 0);
+ case TP_CONNECTION_STATUS_CONNECTED:
+ {
+ tp_base_contact_list_set_list_received (TP_BASE_CONTACT_LIST (self));
+ }
+ break;
- if (tp_channel_manager_asv_has_unknown_properties (request_properties,
- fixed_properties, allowed_properties, &error))
- {
- goto error;
+ case TP_CONNECTION_STATUS_DISCONNECTED:
+ {
+ close_all (self);
+ }
+ break;
}
+}
- if (handle_type == TP_HANDLE_TYPE_LIST)
- {
- /* telepathy-glib has already checked that the handle is valid */
- g_assert (handle < NUM_TP_TESTS_CONTACT_LISTS);
-
- chan = TP_TESTS_CONTACT_LIST_BASE (self->priv->lists[handle]);
- }
- else
- {
- chan = g_hash_table_lookup (self->priv->groups,
- GUINT_TO_POINTER (handle));
- }
+static void
+constructed (GObject *object)
+{
+ TpTestsContactListManager *self = TP_TESTS_CONTACT_LIST_MANAGER (object);
+ void (*chain_up) (GObject *) =
+ ((GObjectClass *) tp_tests_contact_list_manager_parent_class)->constructed;
- if (chan == NULL)
- {
- new_channel (self, handle_type, handle, request_token);
- }
- else if (require_new)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "A ContactList channel for type #%u, handle #%u already exists",
- handle_type, handle);
- goto error;
- }
- else
+ if (chain_up != NULL)
{
- tp_channel_manager_emit_request_already_satisfied (self,
- request_token, TP_EXPORTABLE_CHANNEL (chan));
+ chain_up (object);
}
- return TRUE;
+ self->priv->conn = tp_base_contact_list_get_connection (
+ TP_BASE_CONTACT_LIST (self), NULL);
+ self->priv->status_changed_id = g_signal_connect (self->priv->conn,
+ "status-changed", G_CALLBACK (status_changed_cb), self);
-error:
- tp_channel_manager_emit_request_failed (self, request_token,
- error->domain, error->code, error->message);
- g_error_free (error);
- return TRUE;
+ self->priv->contact_repo = tp_base_connection_get_handles (self->priv->conn,
+ TP_HANDLE_TYPE_CONTACT);
+ self->priv->group_repo = tp_base_connection_get_handles (self->priv->conn,
+ TP_HANDLE_TYPE_GROUP);
+ self->priv->groups = tp_handle_set_new (self->priv->group_repo);
}
-static gboolean
-tp_tests_contact_list_manager_create_channel (TpChannelManager *manager,
- gpointer request_token,
- GHashTable *request_properties)
+static void
+contact_groups_iface_init (TpContactGroupListInterface *iface)
{
- return tp_tests_contact_list_manager_request (
- TP_TESTS_CONTACT_LIST_MANAGER (manager), request_token,
- request_properties, TRUE);
+ iface->dup_groups = contact_list_dup_groups;
+ iface->dup_contact_groups = contact_list_dup_contact_groups;
+ iface->dup_group_members = contact_list_dup_group_members;
}
-static gboolean
-tp_tests_contact_list_manager_ensure_channel (TpChannelManager *manager,
- gpointer request_token,
- GHashTable *request_properties)
+static void
+mutable_contact_groups_iface_init (
+ TpMutableContactGroupListInterface *iface)
{
- return tp_tests_contact_list_manager_request (
- TP_TESTS_CONTACT_LIST_MANAGER (manager), request_token,
- request_properties, FALSE);
+ iface->set_contact_groups_async = contact_list_set_contact_groups_async;
+ iface->set_group_members_async = contact_list_set_group_members_async;
+ iface->add_to_group_async = contact_list_add_to_group_async;
+ iface->remove_from_group_async = contact_list_remove_from_group_async;
+ iface->remove_group_async = contact_list_remove_group_async;
}
static void
-channel_manager_iface_init (gpointer g_iface,
- gpointer data G_GNUC_UNUSED)
+mutable_iface_init (TpMutableContactListInterface *iface)
{
- TpChannelManagerIface *iface = g_iface;
-
- iface->foreach_channel = tp_tests_contact_list_manager_foreach_channel;
- iface->foreach_channel_class =
- tp_tests_contact_list_manager_foreach_channel_class;
- iface->create_channel = tp_tests_contact_list_manager_create_channel;
- iface->ensure_channel = tp_tests_contact_list_manager_ensure_channel;
- /* In this channel manager, Request has the same semantics as Ensure */
- iface->request_channel = tp_tests_contact_list_manager_ensure_channel;
+ iface->request_subscription_async = contact_list_request_subscription_async;
+ iface->authorize_publication_async = contact_list_authorize_publication_async;
+ iface->remove_contacts_async = contact_list_remove_contacts_async;
+ iface->unsubscribe_async = contact_list_unsubscribe_async;
+ iface->unpublish_async = contact_list_unpublish_async;
}
static void
-send_updated_roster (TpTestsContactListManager *self,
- TpHandle contact)
+tp_tests_contact_list_manager_class_init (TpTestsContactListManagerClass *klass)
{
- TpTestsContactDetails *d = g_hash_table_lookup (self->priv->contact_details,
- GUINT_TO_POINTER (contact));
- const gchar *identifier = tp_handle_inspect (self->priv->contact_repo,
- contact);
-
- /* In a real connection manager, we'd transmit these new details to the
- * server, rather than just printing messages. */
-
- if (d == NULL)
- {
- g_message ("Deleting contact %s from server", identifier);
- }
- else
- {
- TpHandle handle;
-
- g_message ("Transmitting new state of contact %s to server", identifier);
- g_message ("\talias = %s", d->alias);
- g_message ("\tcan see our presence = %s",
- d->publish ? "yes" :
- (d->publish_requested ? "no, but has requested it" : "no"));
- g_message ("\tsends us presence = %s",
- d->subscribe ? "yes" :
- (d->subscribe_requested ? "no, but we have requested it" : "no"));
-
- if (d->tags == NULL || tp_handle_set_size (d->tags) == 0)
- {
- g_message ("\tnot in any groups");
- }
- else
- {
- TpIntSet *set = tp_handle_set_peek (d->tags);
- TpIntSetFastIter iter;
- TpHandle member;
-
- tp_intset_fast_iter_init (&iter, set);
-
- while (tp_intset_fast_iter_next (&iter, &member))
- {
- g_message ("\tin group: %s",
- tp_handle_inspect (self->priv->group_repo, member));
- }
- }
+ GObjectClass *object_class = (GObjectClass *) klass;
+ TpBaseContactListClass *base_class =(TpBaseContactListClass *) klass;
- if (d->contact_info == NULL)
- {
- g_message ("\tno contact info");
- }
- else
- {
- for (guint i = 0; i < d->contact_info->len; i++)
- {
- GValueArray *va = g_ptr_array_index (d->contact_info, i);
-
- GValue *gv0, *gv1, *gv2;
- gchar **params, **values;
- gchar *empty_strv[] = { NULL };
-
- gv0 = g_value_array_get_nth (va, 0);
- gv1 = g_value_array_get_nth (va, 1);
- gv2 = g_value_array_get_nth (va, 2);
- params = g_value_peek_pointer (gv1);
- values = g_value_peek_pointer (gv2);
-
- if (params == NULL)
- params = empty_strv;
- if (values == NULL)
- values = empty_strv;
-
- g_message ("\tcontact info:");
- g_message ("\t\tname: %s", g_value_get_string (gv0));
- g_message ("\t\tparams:");
- for (guint j = 0; j < g_strv_length (params); j++)
- {
- g_message ("\t\t\t%s", params[j]);
- }
- g_message ("\t\tvalues:");
- for (guint j = 0; j < g_strv_length (values); j++)
- {
- g_message ("\t\t\t%s", values[j]);
- }
- }
- }
+ g_type_class_add_private (klass, sizeof (TpTestsContactListManagerPrivate));
- handle = tp_handle_ensure (self->priv->contact_repo, d->id, NULL, NULL);
- /* XXX: ideally, we'd only do this if thse specific details really
- * changed, but it's not terribly unrealistic to think some servers or CMs
- * would make this mistake as well. */
- g_signal_emit (self, signals[ALIAS_UPDATED], 0, handle);
- g_signal_emit (self, signals[PRESENCE_UPDATED], 0, handle);
- g_signal_emit (self, signals[CONTACT_INFO_UPDATED], 0, handle);
+ object_class->constructed = constructed;
+ object_class->dispose = dispose;
- tp_handle_unref (self->priv->contact_repo, handle);
- }
+ base_class->dup_states = contact_list_dup_states;
+ base_class->dup_contacts = contact_list_dup_contacts;
}
-gboolean
+void
tp_tests_contact_list_manager_add_to_group (TpTestsContactListManager *self,
- GObject *channel,
- TpHandle group,
- TpHandle member,
- const gchar *message,
- GError **error)
+ const gchar *group_name, TpHandle member)
{
- gboolean updated;
- TpTestsContactDetails *d = ensure_contact (self, member, &updated);
- TpTestsContactList *stored = self->priv->lists[
- TP_TESTS_CONTACT_LIST_STORED];
+ TpBaseContactList *base = TP_BASE_CONTACT_LIST (self);
+ ContactDetails *d = ensure_contact (self, member);
+ TpHandle group_handle;
- if (d->tags == NULL)
- d->tags = tp_handle_set_new (self->priv->group_repo);
+ group_handle = tp_handle_ensure (self->priv->group_repo,
+ group_name, NULL, NULL);
- if (!tp_handle_set_is_member (d->tags, group))
+ if (!tp_handle_set_is_member (self->priv->groups, group_handle))
{
- tp_handle_set_add (d->tags, group);
- updated = TRUE;
+ tp_handle_set_add (self->priv->groups, group_handle);
+ tp_base_contact_list_groups_created ((TpBaseContactList *) self,
+ &group_name, 1);
}
- if (updated)
- {
- TpIntSet *added = tp_intset_new_containing (member);
-
- send_updated_roster (self, member);
- tp_group_mixin_change_members (channel, "", added, NULL, NULL, NULL,
- self->priv->conn->self_handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_group_mixin_change_members ((GObject *) stored, "",
- added, NULL, NULL, NULL,
- self->priv->conn->self_handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (added);
- }
-
- return TRUE;
+ tp_handle_set_add (d->groups, group_handle);
+ tp_base_contact_list_one_contact_groups_changed (base, member,
+ &group_name, 1, NULL, 0);
}
-gboolean
-tp_tests_contact_list_manager_remove_from_group (
- TpTestsContactListManager *self,
- GObject *channel,
- TpHandle group,
- TpHandle member,
- const gchar *message,
- GError **error)
+void
+tp_tests_contact_list_manager_remove_from_group (TpTestsContactListManager *self,
+ const gchar *group_name, TpHandle member)
{
- TpTestsContactDetails *d = lookup_contact (self, member);
-
- /* If not on the roster or not in any groups, we have nothing to do */
- if (d == NULL || d->tags == NULL)
- return TRUE;
+ TpBaseContactList *base = TP_BASE_CONTACT_LIST (self);
+ ContactDetails *d = lookup_contact (self, member);
+ TpHandle group_handle;
- if (tp_handle_set_remove (d->tags, group))
- {
- TpIntSet *removed = tp_intset_new_containing (member);
+ if (d == NULL)
+ return;
- send_updated_roster (self, member);
- tp_group_mixin_change_members (channel, "", NULL, removed, NULL, NULL,
- self->priv->conn->self_handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (removed);
- }
+ group_handle = tp_handle_ensure (self->priv->group_repo, group_name, NULL, NULL);
- return TRUE;
+ tp_handle_set_remove (d->groups, group_handle);
+ tp_base_contact_list_one_contact_groups_changed (base, member,
+ NULL, 0, &group_name, 1);
}
typedef struct {
TpTestsContactListManager *self;
- TpHandle contact;
+ TpHandleSet *handles;
} SelfAndContact;
static SelfAndContact *
self_and_contact_new (TpTestsContactListManager *self,
- TpHandle contact)
+ TpHandleSet *handles)
{
SelfAndContact *ret = g_slice_new0 (SelfAndContact);
ret->self = g_object_ref (self);
- ret->contact = contact;
- tp_handle_ref (self->priv->contact_repo, contact);
+ ret->handles = tp_handle_set_copy (handles);
+
return ret;
}
@@ -1294,98 +665,41 @@ self_and_contact_destroy (gpointer p)
{
SelfAndContact *s = p;
- tp_handle_unref (s->self->priv->contact_repo, s->contact);
+ tp_handle_set_destroy (s->handles);
g_object_unref (s->self);
g_slice_free (SelfAndContact, s);
}
-static void
-receive_auth_request (TpTestsContactListManager *self,
- TpHandle contact)
-{
- TpTestsContactDetails *d;
- TpIntSet *set;
- TpTestsContactList *publish = self->priv->lists[
- TP_TESTS_CONTACT_LIST_PUBLISH];
- TpTestsContactList *stored = self->priv->lists[
- TP_TESTS_CONTACT_LIST_STORED];
-
- /* if shutting down, do nothing */
- if (publish == NULL)
- return;
-
- /* A remote contact has asked to see our presence.
- *
- * In a real connection manager this would be the result of incoming
- * data from the server. */
-
- g_message ("From server: %s has sent us a publish request",
- tp_handle_inspect (self->priv->contact_repo, contact));
-
- d = ensure_contact (self, contact, NULL);
-
- if (d->publish)
- return;
-
- d->publish_requested = TRUE;
-
- set = tp_intset_new_containing (contact);
- tp_group_mixin_change_members ((GObject *) publish,
- "May I see your presence, please?",
- NULL, NULL, set, NULL,
- contact, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_group_mixin_change_members ((GObject *) stored, "",
- set, NULL, NULL, NULL,
- contact, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (set);
-}
-
static gboolean
receive_authorized (gpointer p)
{
SelfAndContact *s = p;
- TpTestsContactDetails *d;
- TpIntSet *set;
- TpTestsContactList *subscribe = s->self->priv->lists[
- TP_TESTS_CONTACT_LIST_SUBSCRIBE];
- TpTestsContactList *stored = s->self->priv->lists[
- TP_TESTS_CONTACT_LIST_STORED];
-
- /* A remote contact has accepted our request to see their presence.
- *
- * In a real connection manager this would be the result of incoming
- * data from the server. */
-
- g_message ("From server: %s has accepted our subscribe request",
- tp_handle_inspect (s->self->priv->contact_repo, s->contact));
-
- d = ensure_contact (s->self, s->contact, NULL);
-
- /* if we were already subscribed to them, then nothing really happened */
- if (d->subscribe)
- return FALSE;
-
- d->subscribe_requested = FALSE;
- d->subscribe = TRUE;
-
- set = tp_intset_new_containing (s->contact);
- tp_group_mixin_change_members ((GObject *) subscribe, "",
- set, NULL, NULL, NULL,
- s->contact, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_group_mixin_change_members ((GObject *) stored, "",
- set, NULL, NULL, NULL,
- s->contact, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (set);
-
- /* their presence changes to something other than UNKNOWN */
- g_signal_emit (s->self, signals[PRESENCE_UPDATED], 0, s->contact);
+ GArray *handles_array;
+ guint i;
- /* if we're not publishing to them, also pretend they have asked us to
- * do so */
- if (!d->publish)
+ handles_array = tp_handle_set_to_array (s->handles);
+ for (i = 0; i < handles_array->len; i++)
{
- receive_auth_request (s->self, s->contact);
+ ContactDetails *d = lookup_contact (s->self,
+ g_array_index (handles_array, TpHandle, i));
+
+ if (d == NULL)
+ continue;
+
+ d->subscribe = TP_SUBSCRIPTION_STATE_YES;
+
+ /* if we're not publishing to them, also pretend they have asked us to do so */
+ if (d->publish != TP_SUBSCRIPTION_STATE_YES)
+ {
+ d->publish = TP_SUBSCRIPTION_STATE_ASK;
+ tp_clear_pointer (&d->publish_request, g_free);
+ d->publish_request = g_strdup ("automatic publish request");
+ }
}
+ g_array_unref (handles_array);
+
+ tp_base_contact_list_contacts_changed (TP_BASE_CONTACT_LIST (s->self),
+ s->handles, NULL);
return FALSE;
}
@@ -1394,477 +708,200 @@ static gboolean
receive_unauthorized (gpointer p)
{
SelfAndContact *s = p;
- TpTestsContactDetails *d;
- TpIntSet *set;
- TpTestsContactList *subscribe = s->self->priv->lists[
- TP_TESTS_CONTACT_LIST_SUBSCRIBE];
-
- /* if shutting down, do nothing */
- if (subscribe == NULL)
- return FALSE;
-
- /* A remote contact has rejected our request to see their presence.
- *
- * In a real connection manager this would be the result of incoming
- * data from the server. */
-
- g_message ("From server: %s has rejected our subscribe request",
- tp_handle_inspect (s->self->priv->contact_repo, s->contact));
-
- d = ensure_contact (s->self, s->contact, NULL);
+ GArray *handles_array;
+ guint i;
- if (!d->subscribe && !d->subscribe_requested)
- return FALSE;
+ handles_array = tp_handle_set_to_array (s->handles);
+ for (i = 0; i < handles_array->len; i++)
+ {
+ ContactDetails *d = lookup_contact (s->self,
+ g_array_index (handles_array, TpHandle, i));
- d->subscribe_requested = FALSE;
- d->subscribe = FALSE;
+ if (d == NULL)
+ continue;
- set = tp_intset_new_containing (s->contact);
- tp_group_mixin_change_members ((GObject *) subscribe, "Say 'please'!",
- NULL, set, NULL, NULL,
- s->contact, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (set);
+ d->subscribe = TP_SUBSCRIPTION_STATE_REMOVED_REMOTELY;
+ }
+ g_array_unref (handles_array);
- /* their presence changes to UNKNOWN */
- g_signal_emit (s->self, signals[PRESENCE_UPDATED], 0, s->contact);
+ tp_base_contact_list_contacts_changed (TP_BASE_CONTACT_LIST (s->self),
+ s->handles, NULL);
return FALSE;
}
-gboolean
-tp_tests_contact_list_manager_add_to_list (TpTestsContactListManager *self,
- GObject *channel,
- TpTestsContactListHandle list,
- TpHandle member,
- const gchar *message,
- GError **error)
+void
+tp_tests_contact_list_manager_request_subscription (TpTestsContactListManager *self,
+ guint n_members, TpHandle *members, const gchar *message)
{
- TpIntSet *set;
- TpTestsContactList *stored = self->priv->lists[TP_TESTS_CONTACT_LIST_STORED];
+ TpHandleSet *handles;
+ guint i;
+ gchar *message_lc;
- switch (list)
+ handles = tp_handle_set_new (self->priv->contact_repo);
+ for (i = 0; i < n_members; i++)
{
- case TP_TESTS_CONTACT_LIST_SUBSCRIBE:
- /* we would like to see member's presence */
- {
- gboolean created;
- TpTestsContactDetails *d = ensure_contact (self, member, &created);
- gchar *message_lc;
-
- /* if they already authorized us, it's a no-op */
- if (d->subscribe)
- return TRUE;
-
- /* In a real connection manager we'd start a network request here */
- g_message ("Transmitting authorization request to %s: %s",
- tp_handle_inspect (self->priv->contact_repo, member),
- message);
-
- if (created || !d->subscribe_requested)
- {
- d->subscribe_requested = TRUE;
- send_updated_roster (self, member);
- }
-
- set = tp_intset_new_containing (member);
- tp_group_mixin_change_members (channel, message,
- NULL, NULL, NULL, set,
- self->priv->conn->self_handle,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- /* subscribing to someone implicitly puts them on Stored, too */
- tp_group_mixin_change_members ((GObject *) stored, "",
- set, NULL, NULL, NULL,
- self->priv->conn->self_handle,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (set);
-
- /* Pretend that after a delay, the contact notices the request
- * and allows or rejects it. In this tp_test connection manager,
- * empty requests are allowed, as are requests that contain "please"
- * case-insensitively. All other requests are denied. */
- message_lc = g_ascii_strdown (message, -1);
-
- if (message[0] == '\0' || strstr (message_lc, "please") != NULL)
- {
- g_timeout_add_full (G_PRIORITY_DEFAULT,
- self->priv->simulation_delay, receive_authorized,
- self_and_contact_new (self, member),
- self_and_contact_destroy);
- }
- else
- {
- g_timeout_add_full (G_PRIORITY_DEFAULT,
- self->priv->simulation_delay,
- receive_unauthorized,
- self_and_contact_new (self, member),
- self_and_contact_destroy);
- }
-
- g_free (message_lc);
- }
- return TRUE;
-
- case TP_TESTS_CONTACT_LIST_PUBLISH:
- /* We would like member to see our presence. This is meaningless,
- * unless they have asked for it. */
- {
- TpTestsContactDetails *d = lookup_contact (self, member);
-
- if (d == NULL || !d->publish_requested)
- {
- /* the group mixin won't actually allow this to be reached,
- * because of the flags we set */
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "Can't unilaterally send presence to %s",
- tp_handle_inspect (self->priv->contact_repo, member));
- return FALSE;
- }
-
- if (!d->publish)
- {
- d->publish = TRUE;
- d->publish_requested = FALSE;
- send_updated_roster (self, member);
-
- set = tp_intset_new_containing (member);
- tp_group_mixin_change_members (channel, "",
- set, NULL, NULL, NULL,
- self->priv->conn->self_handle,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_group_mixin_change_members ((GObject *) stored, "",
- set, NULL, NULL, NULL,
- self->priv->conn->self_handle,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (set);
- }
- }
- return TRUE;
-
- case TP_TESTS_CONTACT_LIST_STORED:
- /* we would like member to be on the roster */
- {
- gboolean created;
-
- ensure_contact (self, member, &created);
+ ContactDetails *d = ensure_contact (self, members[i]);
- if (created)
- send_updated_roster (self, member);
+ if (d->subscribe == TP_SUBSCRIPTION_STATE_YES)
+ continue;
- set = tp_intset_new_containing (member);
- tp_group_mixin_change_members (channel, "",
- set, NULL, NULL, NULL, self->priv->conn->self_handle,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (set);
- }
- return TRUE;
-
- case INVALID_TP_TESTS_CONTACT_LIST:
- default:
- g_return_val_if_reached (FALSE);
+ d->subscribe = TP_SUBSCRIPTION_STATE_ASK;
+ tp_handle_set_add (handles, members[i]);
}
-}
-static gboolean
-auth_request_cb (gpointer p)
-{
- SelfAndContact *s = p;
+ tp_base_contact_list_contacts_changed (TP_BASE_CONTACT_LIST (self), handles,
+ NULL);
- receive_auth_request (s->self, s->contact);
+ message_lc = g_ascii_strdown (message, -1);
+ if (strstr (message_lc, "please") != NULL)
+ {
+ g_idle_add_full (G_PRIORITY_DEFAULT,
+ receive_authorized,
+ self_and_contact_new (self, handles),
+ self_and_contact_destroy);
+ }
+ else if (strstr (message_lc, "no") != NULL)
+ {
+ g_idle_add_full (G_PRIORITY_DEFAULT,
+ receive_unauthorized,
+ self_and_contact_new (self, handles),
+ self_and_contact_destroy);
+ }
- return FALSE;
+ g_free (message_lc);
+ tp_handle_set_destroy (handles);
}
-gboolean
-tp_tests_contact_list_manager_remove_from_list (TpTestsContactListManager *self,
- GObject *channel,
- TpTestsContactListHandle list,
- TpHandle member,
- const gchar *message,
- GError **error)
+void
+tp_tests_contact_list_manager_unsubscribe (TpTestsContactListManager *self,
+ guint n_members, TpHandle *members)
{
- TpIntSet *set;
+ TpHandleSet *handles;
+ guint i;
- switch (list)
+ handles = tp_handle_set_new (self->priv->contact_repo);
+ for (i = 0; i < n_members; i++)
{
- case TP_TESTS_CONTACT_LIST_PUBLISH:
- /* we would like member not to see our presence any more, or we
- * would like to reject a request from them to see our presence */
- {
- TpTestsContactDetails *d = lookup_contact (self, member);
-
- if (d != NULL)
- {
- if (d->publish_requested)
- {
- g_message ("Rejecting authorization request from %s",
- tp_handle_inspect (self->priv->contact_repo, member));
- d->publish_requested = FALSE;
-
- set = tp_intset_new_containing (member);
- tp_group_mixin_change_members (channel, "",
- NULL, set, NULL, NULL,
- self->priv->conn->self_handle,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (set);
- }
- else if (d->publish)
- {
- g_message ("Removing authorization from %s",
- tp_handle_inspect (self->priv->contact_repo, member));
- d->publish = FALSE;
-
- set = tp_intset_new_containing (member);
- tp_group_mixin_change_members (channel, "",
- NULL, set, NULL, NULL,
- self->priv->conn->self_handle,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (set);
-
- /* Pretend that after a delay, the contact notices the change
- * and asks for our presence again */
- g_timeout_add_full (G_PRIORITY_DEFAULT,
- self->priv->simulation_delay, auth_request_cb,
- self_and_contact_new (self, member),
- self_and_contact_destroy);
- }
- else
- {
- /* nothing to do, avoid "updating the roster" */
- return TRUE;
- }
-
- send_updated_roster (self, member);
- }
- }
- return TRUE;
+ ContactDetails *d = lookup_contact (self, members[i]);
- case TP_TESTS_CONTACT_LIST_SUBSCRIBE:
- /* we would like to avoid receiving member's presence any more,
- * or we would like to cancel an outstanding request for their
- * presence */
- {
- TpTestsContactDetails *d = lookup_contact (self, member);
-
- if (d != NULL)
- {
- if (d->subscribe_requested)
- {
- g_message ("Cancelling our authorization request to %s",
- tp_handle_inspect (self->priv->contact_repo, member));
- d->subscribe_requested = FALSE;
-
- set = tp_intset_new_containing (member);
- tp_group_mixin_change_members (channel, "",
- NULL, set, NULL, NULL,
- self->priv->conn->self_handle,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (set);
- }
- else if (d->subscribe)
- {
- g_message ("We no longer want presence from %s",
- tp_handle_inspect (self->priv->contact_repo, member));
- d->subscribe = FALSE;
-
- set = tp_intset_new_containing (member);
- tp_group_mixin_change_members (channel, "",
- NULL, set, NULL, NULL,
- self->priv->conn->self_handle,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (set);
-
- /* since they're no longer on the subscribe list, we can't
- * see their presence, so emit a signal changing it to
- * UNKNOWN */
- g_signal_emit (self, signals[PRESENCE_UPDATED], 0, member);
- }
- else
- {
- /* nothing to do, avoid "updating the roster" */
- return TRUE;
- }
-
- send_updated_roster (self, member);
- }
- }
- return TRUE;
-
- case TP_TESTS_CONTACT_LIST_STORED:
- /* we would like to remove member from the roster altogether */
- {
- TpTestsContactDetails *d = lookup_contact (self, member);
-
- if (d != NULL)
- {
- g_hash_table_remove (self->priv->contact_details,
- GUINT_TO_POINTER (member));
- send_updated_roster (self, member);
-
- set = tp_intset_new_containing (member);
- tp_group_mixin_change_members (channel, "",
- NULL, set, NULL, NULL,
- self->priv->conn->self_handle,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_group_mixin_change_members (
- (GObject *) self->priv->lists[TP_TESTS_CONTACT_LIST_SUBSCRIBE],
- "", NULL, set, NULL, NULL,
- self->priv->conn->self_handle,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_group_mixin_change_members (
- (GObject *) self->priv->lists[TP_TESTS_CONTACT_LIST_PUBLISH],
- "", NULL, set, NULL, NULL,
- self->priv->conn->self_handle,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (set);
-
- tp_handle_set_remove (self->priv->contacts, member);
-
- /* since they're no longer on the subscribe list, we can't
- * see their presence, so emit a signal changing it to
- * UNKNOWN */
- g_signal_emit (self, signals[PRESENCE_UPDATED], 0, member);
-
- }
- }
- return TRUE;
+ if (d == NULL || d->subscribe == TP_SUBSCRIPTION_STATE_NO)
+ continue;
- case INVALID_TP_TESTS_CONTACT_LIST:
- default:
- g_return_val_if_reached (FALSE);
+ d->subscribe = TP_SUBSCRIPTION_STATE_NO;
+ tp_handle_set_add (handles, members[i]);
}
+
+ tp_base_contact_list_contacts_changed (TP_BASE_CONTACT_LIST (self), handles,
+ NULL);
+
+ tp_handle_set_destroy (handles);
}
-TpTestsContactListPresence
-tp_tests_contact_list_manager_get_presence (TpTestsContactListManager *self,
- TpHandle contact)
+void
+tp_tests_contact_list_manager_authorize_publication (TpTestsContactListManager *self,
+ guint n_members, TpHandle *members)
{
- TpTestsContactDetails *d = lookup_contact (self, contact);
- const gchar *id;
+ TpHandleSet *handles;
+ guint i;
- if (d == NULL || !d->subscribe)
+ handles = tp_handle_set_new (self->priv->contact_repo);
+ for (i = 0; i < n_members; i++)
{
- /* we don't know the presence of people not on the subscribe list,
- * by definition */
- return TP_TESTS_CONTACT_LIST_PRESENCE_UNKNOWN;
- }
+ ContactDetails *d = lookup_contact (self, members[i]);
- id = tp_handle_inspect (self->priv->contact_repo, contact);
+ if (d == NULL || d->publish != TP_SUBSCRIPTION_STATE_ASK)
+ continue;
- /* In this tp_test CM, we fake contacts' presence based on their name:
- * contacts in the first half of the alphabet are available, the rest
- * (including non-alphabetic and non-ASCII initial letters) are away. */
- if ((id[0] >= 'A' && id[0] <= 'M') || (id[0] >= 'a' && id[0] <= 'm'))
- {
- return TP_TESTS_CONTACT_LIST_PRESENCE_AVAILABLE;
+ d->publish = TP_SUBSCRIPTION_STATE_YES;
+ tp_clear_pointer (&d->publish_request, g_free);
+ tp_handle_set_add (handles, members[i]);
}
- return TP_TESTS_CONTACT_LIST_PRESENCE_AWAY;
+ tp_base_contact_list_contacts_changed (TP_BASE_CONTACT_LIST (self), handles,
+ NULL);
+
+ tp_handle_set_destroy (handles);
}
-const gchar *
-tp_tests_contact_list_manager_get_alias (TpTestsContactListManager *self,
- TpHandle contact)
+void
+tp_tests_contact_list_manager_unpublish (TpTestsContactListManager *self,
+ guint n_members, TpHandle *members)
{
- TpTestsContactDetails *d = lookup_contact (self, contact);
+ TpHandleSet *handles;
+ guint i;
- if (d == NULL)
+ handles = tp_handle_set_new (self->priv->contact_repo);
+ for (i = 0; i < n_members; i++)
{
- /* we don't have a user-defined alias for people not on the roster */
- return tp_handle_inspect (self->priv->contact_repo, contact);
+ ContactDetails *d = lookup_contact (self, members[i]);
+
+ if (d == NULL || d->publish == TP_SUBSCRIPTION_STATE_NO)
+ continue;
+
+ d->publish = TP_SUBSCRIPTION_STATE_NO;
+ tp_clear_pointer (&d->publish_request, g_free);
+ tp_handle_set_add (handles, members[i]);
}
- return d->alias;
+ tp_base_contact_list_contacts_changed (TP_BASE_CONTACT_LIST (self), handles,
+ NULL);
+
+ tp_handle_set_destroy (handles);
}
void
-tp_tests_contact_list_manager_set_alias (TpTestsContactListManager *self,
- TpHandle contact,
- const gchar *alias)
+tp_tests_contact_list_manager_remove (TpTestsContactListManager *self,
+ guint n_members, TpHandle *members)
{
- gboolean created;
- TpTestsContactDetails *d = ensure_contact (self, contact, &created);
- TpTestsContactList *stored = self->priv->lists[
- TP_TESTS_CONTACT_LIST_STORED];
- gchar *old = d->alias;
- TpIntSet *set;
-
- /* FIXME: if stored list hasn't been retrieved yet, queue the change for
- * later */
-
- /* if shutting down, do nothing */
- if (stored == NULL)
- return;
+ TpHandleSet *handles;
+ guint i;
- d->alias = g_strdup (alias);
+ handles = tp_handle_set_new (self->priv->contact_repo);
+ for (i = 0; i < n_members; i++)
+ {
+ ContactDetails *d = lookup_contact (self, members[i]);
- if (created || tp_strdiff (old, alias))
- send_updated_roster (self, contact);
+ if (d == NULL)
+ continue;
- g_free (old);
+ g_hash_table_remove (self->priv->contact_details,
+ GUINT_TO_POINTER (members[i]));
+ tp_handle_set_add (handles, members[i]);
+ }
- set = tp_intset_new_containing (contact);
- tp_group_mixin_change_members ((GObject *) stored, "",
- set, NULL, NULL, NULL, self->priv->conn->self_handle,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (set);
+ tp_base_contact_list_contacts_changed (TP_BASE_CONTACT_LIST (self), NULL,
+ handles);
+
+ tp_handle_set_destroy (handles);
}
-GPtrArray *
-tp_tests_contact_list_manager_get_contact_info (TpTestsContactListManager *self,
- TpHandle contact)
+void
+tp_tests_contact_list_manager_add_initial_contacts (TpTestsContactListManager *self,
+ guint n_members, TpHandle *members)
{
- TpTestsContactDetails *d = lookup_contact (self, contact);
+ TpHandleSet *handles;
+ guint i;
- if (d != NULL)
- return d->contact_info;
+ g_assert_cmpint (self->priv->conn->status, ==,
+ TP_INTERNAL_CONNECTION_STATUS_NEW);
- return NULL;
-}
+ handles = tp_handle_set_new (self->priv->contact_repo);
+ for (i = 0; i < n_members; i++)
+ {
+ ContactDetails *d;
-void
-tp_tests_contact_list_manager_set_contact_info (TpTestsContactListManager *self,
- const GPtrArray *contact_info)
-{
- TpTestsContactList *stored = self->priv->lists[
- TP_TESTS_CONTACT_LIST_STORED];
- GPtrArray *old;
- TpTestsContactDetails *d = ensure_contact (self, self->priv->conn->self_handle,
- NULL);
- d->id = g_strdup (tp_handle_inspect (self->priv->contact_repo,
- self->priv->conn->self_handle));
- old = d->contact_info;
+ g_assert (lookup_contact (self, members[i]) == NULL);
+ d = ensure_contact (self, members[i]);
- /* FIXME: if stored list hasn't been retrieved yet, queue the change for
- * later */
+ d->subscribe = TP_SUBSCRIPTION_STATE_YES;
+ d->publish = TP_SUBSCRIPTION_STATE_YES;
- /* if shutting down, do nothing */
- if (stored == NULL)
- return;
+ tp_handle_set_add (handles, members[i]);
+ }
+
+ tp_base_contact_list_contacts_changed (TP_BASE_CONTACT_LIST (self), handles,
+ NULL);
- d->contact_info = dbus_g_type_specialized_construct (
- TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST);
- {
- guint i;
- for (i = 0; i < contact_info->len; i++)
- {
- const gchar *name;
- const gchar * const * params;
- const gchar * const * values;
- GValueArray *va = g_ptr_array_index (contact_info, i);
-
- tp_value_array_unpack (va, 3,
- &name,
- ¶ms,
- &values);
-
- _insert_contact_field (d->contact_info, name, params, values);
- }
- }
-
- /* always send the updated roster, since it's not worth checking the
- * contact_info for changes */
- send_updated_roster (self, self->priv->conn->self_handle);
-
- if (old != NULL)
- g_ptr_array_unref (old);
+ tp_handle_set_destroy (handles);
}
diff --git a/tests/lib/telepathy/contactlist/contact-list-manager.h b/tests/lib/telepathy/contactlist/contact-list-manager.h
index 8c480b9..8be787c 100644
--- a/tests/lib/telepathy/contactlist/contact-list-manager.h
+++ b/tests/lib/telepathy/contactlist/contact-list-manager.h
@@ -1,8 +1,8 @@
/*
* Example channel manager for contact lists
*
- * Copyright  2007-2009 Collabora Ltd. <http://www.collabora.co.uk/>
- * Copyright  2007-2009 Nokia Corporation
+ * Copyright  2007-2010 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright  2007-2010 Nokia Corporation
*
* Copying and distribution of this file, with or without modification,
* are permitted in any medium without royalty provided the copyright
@@ -12,30 +12,10 @@
#ifndef __TP_TESTS_CONTACT_LIST_MANAGER_H__
#define __TP_TESTS_CONTACT_LIST_MANAGER_H__
-#include <glib-object.h>
-
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/handle.h>
-#include <telepathy-glib/presence-mixin.h>
+#include <telepathy-glib/base-contact-list.h>
G_BEGIN_DECLS
-typedef struct _TpTestsContactListManager TpTestsContactListManager;
-typedef struct _TpTestsContactListManagerClass TpTestsContactListManagerClass;
-typedef struct _TpTestsContactListManagerPrivate TpTestsContactListManagerPrivate;
-
-struct _TpTestsContactListManagerClass {
- GObjectClass parent_class;
-};
-
-struct _TpTestsContactListManager {
- GObject parent;
-
- TpTestsContactListManagerPrivate *priv;
-};
-
-GType tp_tests_contact_list_manager_get_type (void);
-
#define TP_TESTS_TYPE_CONTACT_LIST_MANAGER \
(tp_tests_contact_list_manager_get_type ())
#define TP_TESTS_CONTACT_LIST_MANAGER(obj) \
@@ -52,60 +32,39 @@ GType tp_tests_contact_list_manager_get_type (void);
(G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_CONTACT_LIST_MANAGER, \
TpTestsContactListManagerClass))
-gboolean tp_tests_contact_list_manager_add_to_group (
- TpTestsContactListManager *self, GObject *channel,
- TpHandle group, TpHandle member, const gchar *message, GError **error);
-
-gboolean tp_tests_contact_list_manager_remove_from_group (
- TpTestsContactListManager *self, GObject *channel,
- TpHandle group, TpHandle member, const gchar *message, GError **error);
-
-/* elements 1, 2... of this enum must be kept in sync with elements 0, 1...
- * of the array _contact_lists in contact-list-manager.h */
-typedef enum {
- INVALID_TP_TESTS_CONTACT_LIST,
- TP_TESTS_CONTACT_LIST_SUBSCRIBE = 1,
- TP_TESTS_CONTACT_LIST_PUBLISH,
- TP_TESTS_CONTACT_LIST_STORED
-} TpTestsContactListHandle;
-
-#define NUM_TP_TESTS_CONTACT_LISTS TP_TESTS_CONTACT_LIST_STORED + 1
-
-/* this enum must be kept in sync with the array _statuses in
- * contact-list-manager.c */
-typedef enum {
- TP_TESTS_CONTACT_LIST_PRESENCE_OFFLINE = 0,
- TP_TESTS_CONTACT_LIST_PRESENCE_UNKNOWN,
- TP_TESTS_CONTACT_LIST_PRESENCE_ERROR,
- TP_TESTS_CONTACT_LIST_PRESENCE_AWAY,
- TP_TESTS_CONTACT_LIST_PRESENCE_AVAILABLE
-} TpTestsContactListPresence;
+typedef struct _TpTestsContactListManager TpTestsContactListManager;
+typedef struct _TpTestsContactListManagerClass TpTestsContactListManagerClass;
+typedef struct _TpTestsContactListManagerPrivate TpTestsContactListManagerPrivate;
-const TpPresenceStatusSpec *tp_tests_contact_list_presence_statuses (
- void);
+struct _TpTestsContactListManagerClass {
+ TpBaseContactListClass parent_class;
+};
-gboolean tp_tests_contact_list_manager_add_to_list (
- TpTestsContactListManager *self, GObject *channel,
- TpTestsContactListHandle list, TpHandle member, const gchar *message,
- GError **error);
+struct _TpTestsContactListManager {
+ TpBaseContactList parent;
-gboolean tp_tests_contact_list_manager_remove_from_list (
- TpTestsContactListManager *self, GObject *channel,
- TpTestsContactListHandle list, TpHandle member, const gchar *message,
- GError **error);
+ TpTestsContactListManagerPrivate *priv;
+};
-const gchar **tp_tests_contact_lists (void);
+GType tp_tests_contact_list_manager_get_type (void);
-TpTestsContactListPresence tp_tests_contact_list_manager_get_presence (
- TpTestsContactListManager *self, TpHandle contact);
-const gchar *tp_tests_contact_list_manager_get_alias (
- TpTestsContactListManager *self, TpHandle contact);
-void tp_tests_contact_list_manager_set_alias (
- TpTestsContactListManager *self, TpHandle contact, const gchar *alias);
-GPtrArray * tp_tests_contact_list_manager_get_contact_info (
- TpTestsContactListManager *self, TpHandle contact);
-void tp_tests_contact_list_manager_set_contact_info (
- TpTestsContactListManager *self, const GPtrArray *contact_info);
+void tp_tests_contact_list_manager_add_to_group (TpTestsContactListManager *self,
+ const gchar *group_name, TpHandle member);
+void tp_tests_contact_list_manager_remove_from_group (TpTestsContactListManager *self,
+ const gchar *group_name, TpHandle member);
+
+void tp_tests_contact_list_manager_request_subscription (TpTestsContactListManager *self,
+ guint n_members, TpHandle *members, const gchar *message);
+void tp_tests_contact_list_manager_unsubscribe (TpTestsContactListManager *self,
+ guint n_members, TpHandle *members);
+void tp_tests_contact_list_manager_authorize_publication (TpTestsContactListManager *self,
+ guint n_members, TpHandle *members);
+void tp_tests_contact_list_manager_unpublish (TpTestsContactListManager *self,
+ guint n_members, TpHandle *members);
+void tp_tests_contact_list_manager_remove (TpTestsContactListManager *self,
+ guint n_members, TpHandle *members);
+void tp_tests_contact_list_manager_add_initial_contacts (TpTestsContactListManager *self,
+ guint n_members, TpHandle *members);
G_END_DECLS
diff --git a/tests/lib/telepathy/contactlist/contacts-conn.c b/tests/lib/telepathy/contactlist/contacts-conn.c
new file mode 100644
index 0000000..bd434fd
--- /dev/null
+++ b/tests/lib/telepathy/contactlist/contacts-conn.c
@@ -0,0 +1,1392 @@
+/*
+ * contacts-conn.c - connection with contact info
+ *
+ * Copyright (C) 2007-2008 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright (C) 2007-2008 Nokia Corporation
+ *
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved.
+ */
+
+#include "config.h"
+
+#include "contacts-conn.h"
+
+#include <dbus/dbus-glib.h>
+
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/errors.h>
+#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/handle-repo-dynamic.h>
+#include <telepathy-glib/util.h>
+
+#include "debug.h"
+
+static void init_aliasing (gpointer, gpointer);
+static void init_avatars (gpointer, gpointer);
+static void init_location (gpointer, gpointer);
+static void init_contact_caps (gpointer, gpointer);
+static void init_contact_info (gpointer, gpointer);
+static void conn_avatars_properties_getter (GObject *object, GQuark interface,
+ GQuark name, GValue *value, gpointer getter_data);
+
+G_DEFINE_TYPE_WITH_CODE (TpTestsContactsConnection,
+ tp_tests_contacts_connection,
+ TP_TESTS_TYPE_SIMPLE_CONNECTION,
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING,
+ init_aliasing);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_AVATARS,
+ init_avatars);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_PRESENCE,
+ tp_presence_mixin_iface_init);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_SIMPLE_PRESENCE,
+ tp_presence_mixin_simple_presence_iface_init)
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_LOCATION,
+ init_location)
+ G_IMPLEMENT_INTERFACE (
+ TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_CAPABILITIES,
+ init_contact_caps)
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_INFO,
+ init_contact_info)
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS,
+ tp_contacts_mixin_iface_init);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_LIST,
+ tp_base_contact_list_mixin_list_iface_init);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_GROUPS,
+ tp_base_contact_list_mixin_groups_iface_init);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CLIENT_TYPES,
+ NULL);
+ );
+
+/* type definition stuff */
+
+static const char *mime_types[] = { "image/png", NULL };
+static TpDBusPropertiesMixinPropImpl conn_avatars_properties[] = {
+ { "MinimumAvatarWidth", GUINT_TO_POINTER (1), NULL },
+ { "MinimumAvatarHeight", GUINT_TO_POINTER (2), NULL },
+ { "RecommendedAvatarWidth", GUINT_TO_POINTER (3), NULL },
+ { "RecommendedAvatarHeight", GUINT_TO_POINTER (4), NULL },
+ { "MaximumAvatarWidth", GUINT_TO_POINTER (5), NULL },
+ { "MaximumAvatarHeight", GUINT_TO_POINTER (6), NULL },
+ { "MaximumAvatarBytes", GUINT_TO_POINTER (7), NULL },
+ /* special-cased - it's the only one with a non-guint value */
+ { "SupportedAvatarMIMETypes", NULL, NULL },
+ { NULL }
+};
+
+enum
+{
+ N_SIGNALS
+};
+
+struct _TpTestsContactsConnectionPrivate
+{
+ /* TpHandle => gchar * */
+ GHashTable *aliases;
+ /* TpHandle => AvatarData */
+ GHashTable *avatars;
+ /* TpHandle => ContactsConnectionPresenceStatusIndex */
+ GHashTable *presence_statuses;
+ /* TpHandle => gchar * */
+ GHashTable *presence_messages;
+ /* TpHandle => GHashTable * */
+ GHashTable *locations;
+ /* TpHandle => GPtrArray * */
+ GHashTable *capabilities;
+ /* TpHandle => GPtrArray * */
+ GHashTable *contact_info;
+ GPtrArray *default_contact_info;
+
+ TpTestsContactListManager *list_manager;
+};
+
+typedef struct
+{
+ GArray *data;
+ gchar *mime_type;
+ gchar *token;
+} AvatarData;
+
+static AvatarData *
+avatar_data_new (GArray *data,
+ const gchar *mime_type,
+ const gchar *token)
+{
+ AvatarData *a;
+
+ a = g_slice_new (AvatarData);
+ a->data = data ? g_array_ref (data) : NULL;
+ a->mime_type = g_strdup (mime_type);
+ a->token = g_strdup (token);
+
+ return a;
+}
+
+static void
+avatar_data_free (gpointer data)
+{
+ AvatarData *a = data;
+
+ if (a != NULL)
+ {
+ if (a->data != NULL)
+ g_array_unref (a->data);
+ g_free (a->mime_type);
+ g_free (a->token);
+ g_slice_free (AvatarData, a);
+ }
+}
+
+static void
+free_rcc_list (GPtrArray *rccs)
+{
+ g_boxed_free (TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST, rccs);
+}
+
+static void
+tp_tests_contacts_connection_init (TpTestsContactsConnection *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TESTS_TYPE_CONTACTS_CONNECTION,
+ TpTestsContactsConnectionPrivate);
+ self->priv->aliases = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, g_free);
+ self->priv->avatars = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal, NULL, avatar_data_free);
+ self->priv->presence_statuses = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal, NULL, NULL);
+ self->priv->presence_messages = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal, NULL, g_free);
+ self->priv->locations = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify) g_hash_table_unref);
+ self->priv->capabilities = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal, NULL, (GDestroyNotify) free_rcc_list);
+ self->priv->contact_info = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal, NULL, (GDestroyNotify) g_ptr_array_unref);
+}
+
+static void
+finalize (GObject *object)
+{
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (object);
+
+ tp_contacts_mixin_finalize (object);
+ g_hash_table_unref (self->priv->aliases);
+ g_hash_table_unref (self->priv->avatars);
+ g_hash_table_unref (self->priv->presence_statuses);
+ g_hash_table_unref (self->priv->presence_messages);
+ g_hash_table_unref (self->priv->locations);
+ g_hash_table_unref (self->priv->capabilities);
+ g_hash_table_unref (self->priv->contact_info);
+
+ if (self->priv->default_contact_info != NULL)
+ g_ptr_array_unref (self->priv->default_contact_info);
+
+ G_OBJECT_CLASS (tp_tests_contacts_connection_parent_class)->finalize (object);
+}
+
+static void
+aliasing_fill_contact_attributes (GObject *object,
+ const GArray *contacts,
+ GHashTable *attributes)
+{
+ guint i;
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (object);
+ TpBaseConnection *base = TP_BASE_CONNECTION (object);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base,
+ TP_HANDLE_TYPE_CONTACT);
+
+ for (i = 0; i < contacts->len; i++)
+ {
+ TpHandle handle = g_array_index (contacts, guint, i);
+ const gchar *alias = g_hash_table_lookup (self->priv->aliases,
+ GUINT_TO_POINTER (handle));
+
+ if (alias == NULL)
+ {
+ alias = tp_handle_inspect (contact_repo, handle);
+ }
+
+ tp_contacts_mixin_set_contact_attribute (attributes, handle,
+ TP_IFACE_CONNECTION_INTERFACE_ALIASING "/alias",
+ tp_g_value_slice_new_string (alias));
+ }
+}
+
+static void
+avatars_fill_contact_attributes (GObject *object,
+ const GArray *contacts,
+ GHashTable *attributes)
+{
+ guint i;
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (object);
+
+ for (i = 0; i < contacts->len; i++)
+ {
+ TpHandle handle = g_array_index (contacts, guint, i);
+ AvatarData *a = g_hash_table_lookup (self->priv->avatars,
+ GUINT_TO_POINTER (handle));
+
+ if (a != NULL && a->token != NULL)
+ {
+ tp_contacts_mixin_set_contact_attribute (attributes, handle,
+ TP_IFACE_CONNECTION_INTERFACE_AVATARS "/token",
+ tp_g_value_slice_new_string (a->token));
+ }
+ }
+}
+
+static void
+location_fill_contact_attributes (GObject *object,
+ const GArray *contacts,
+ GHashTable *attributes)
+{
+ guint i;
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (object);
+
+ for (i = 0; i < contacts->len; i++)
+ {
+ TpHandle handle = g_array_index (contacts, guint, i);
+ GHashTable *location = g_hash_table_lookup (self->priv->locations,
+ GUINT_TO_POINTER (handle));
+
+ if (location != NULL)
+ {
+ tp_contacts_mixin_set_contact_attribute (attributes, handle,
+ TP_IFACE_CONNECTION_INTERFACE_LOCATION "/location",
+ tp_g_value_slice_new_boxed (TP_HASH_TYPE_LOCATION, location));
+ }
+ }
+}
+
+static void
+contact_caps_fill_contact_attributes (GObject *object,
+ const GArray *contacts,
+ GHashTable *attributes)
+{
+ guint i;
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (object);
+
+ for (i = 0; i < contacts->len; i++)
+ {
+ TpHandle handle = g_array_index (contacts, guint, i);
+ GPtrArray *caps = g_hash_table_lookup (self->priv->capabilities,
+ GUINT_TO_POINTER (handle));
+
+ if (caps != NULL)
+ {
+ tp_contacts_mixin_set_contact_attribute (attributes, handle,
+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES "/capabilities",
+ tp_g_value_slice_new_boxed (
+ TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST, caps));
+ }
+ }
+}
+
+static void
+contact_info_fill_contact_attributes (GObject *object,
+ const GArray *contacts,
+ GHashTable *attributes)
+{
+ guint i;
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (object);
+
+ for (i = 0; i < contacts->len; i++)
+ {
+ TpHandle handle = g_array_index (contacts, guint, i);
+ GPtrArray *info = g_hash_table_lookup (self->priv->contact_info,
+ GUINT_TO_POINTER (handle));
+
+ if (info != NULL)
+ {
+ tp_contacts_mixin_set_contact_attribute (attributes, handle,
+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO "/info",
+ tp_g_value_slice_new_boxed (TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST,
+ info));
+ }
+ }
+}
+
+static TpDBusPropertiesMixinPropImpl conn_contact_info_properties[] = {
+ { "ContactInfoFlags", GUINT_TO_POINTER (TP_CONTACT_INFO_FLAG_PUSH |
+ TP_CONTACT_INFO_FLAG_CAN_SET), NULL },
+ { "SupportedFields", NULL, NULL },
+ { NULL }
+};
+
+static void
+conn_contact_info_properties_getter (GObject *object,
+ GQuark interface,
+ GQuark name,
+ GValue *value,
+ gpointer getter_data)
+{
+ GQuark q_supported_fields = g_quark_from_static_string ("SupportedFields");
+ static GPtrArray *supported_fields = NULL;
+
+ if (name == q_supported_fields)
+ {
+ if (supported_fields == NULL)
+ {
+ supported_fields = g_ptr_array_new ();
+
+ g_ptr_array_add (supported_fields, tp_value_array_build (4,
+ G_TYPE_STRING, "bday",
+ G_TYPE_STRV, NULL,
+ G_TYPE_UINT, 0,
+ G_TYPE_UINT, 1,
+ G_TYPE_INVALID));
+
+ g_ptr_array_add (supported_fields, tp_value_array_build (4,
+ G_TYPE_STRING, "email",
+ G_TYPE_STRV, NULL,
+ G_TYPE_UINT, 0,
+ G_TYPE_UINT, G_MAXUINT32,
+ G_TYPE_INVALID));
+
+ g_ptr_array_add (supported_fields, tp_value_array_build (4,
+ G_TYPE_STRING, "fn",
+ G_TYPE_STRV, NULL,
+ G_TYPE_UINT, 0,
+ G_TYPE_UINT, 1,
+ G_TYPE_INVALID));
+
+ g_ptr_array_add (supported_fields, tp_value_array_build (4,
+ G_TYPE_STRING, "tel",
+ G_TYPE_STRV, NULL,
+ G_TYPE_UINT, 0,
+ G_TYPE_UINT, G_MAXUINT32,
+ G_TYPE_INVALID));
+
+ g_ptr_array_add (supported_fields, tp_value_array_build (4,
+ G_TYPE_STRING, "url",
+ G_TYPE_STRV, NULL,
+ G_TYPE_UINT, 0,
+ G_TYPE_UINT, G_MAXUINT32,
+ G_TYPE_INVALID));
+ }
+ g_value_set_boxed (value, supported_fields);
+ }
+ else
+ {
+ g_value_set_uint (value, GPOINTER_TO_UINT (getter_data));
+ }
+}
+
+static void
+client_types_fill_contact_attributes (
+ GObject *object,
+ const GArray *contacts,
+ GHashTable *attributes)
+{
+ TpTestsContactsConnectionClass *klass =
+ TP_TESTS_CONTACTS_CONNECTION_GET_CLASS (object);
+
+ if (klass->fill_client_types != NULL)
+ klass->fill_client_types (object, contacts, attributes);
+ /* âelse do nothing: a no-op implementation is valid, relatively speaking.
+ * The spec sez the /client-types attribute should be âomitted from the
+ * result if the contact's client types are not known.â
+ */
+}
+
+static void
+constructed (GObject *object)
+{
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (object);
+ TpBaseConnection *base = TP_BASE_CONNECTION (object);
+ void (*parent_impl) (GObject *) =
+ G_OBJECT_CLASS (tp_tests_contacts_connection_parent_class)->constructed;
+
+ if (parent_impl != NULL)
+ parent_impl (object);
+
+ tp_contacts_mixin_init (object,
+ G_STRUCT_OFFSET (TpTestsContactsConnection, contacts_mixin));
+ tp_base_connection_register_with_contacts_mixin (base);
+ if (self->priv->list_manager)
+ tp_base_contact_list_mixin_register_with_contacts_mixin (base);
+ tp_contacts_mixin_add_contact_attributes_iface (object,
+ TP_IFACE_CONNECTION_INTERFACE_ALIASING,
+ aliasing_fill_contact_attributes);
+ tp_contacts_mixin_add_contact_attributes_iface (object,
+ TP_IFACE_CONNECTION_INTERFACE_AVATARS,
+ avatars_fill_contact_attributes);
+ tp_contacts_mixin_add_contact_attributes_iface (object,
+ TP_IFACE_CONNECTION_INTERFACE_LOCATION,
+ location_fill_contact_attributes);
+ tp_contacts_mixin_add_contact_attributes_iface (object,
+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES,
+ contact_caps_fill_contact_attributes);
+ tp_contacts_mixin_add_contact_attributes_iface (object,
+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO,
+ contact_info_fill_contact_attributes);
+ tp_contacts_mixin_add_contact_attributes_iface (object,
+ TP_IFACE_CONNECTION_INTERFACE_CLIENT_TYPES,
+ client_types_fill_contact_attributes);
+
+ tp_presence_mixin_init (object,
+ G_STRUCT_OFFSET (TpTestsContactsConnection, presence_mixin));
+ tp_presence_mixin_simple_presence_register_with_contacts_mixin (object);
+}
+
+static const TpPresenceStatusOptionalArgumentSpec can_have_message[] = {
+ { "message", "s", NULL, NULL },
+ { NULL }
+};
+
+/* Must match TpTestsContactsConnectionPresenceStatusIndex in the .h */
+static const TpPresenceStatusSpec my_statuses[] = {
+ { "available", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE, TRUE,
+ can_have_message },
+ { "busy", TP_CONNECTION_PRESENCE_TYPE_BUSY, TRUE, can_have_message },
+ { "away", TP_CONNECTION_PRESENCE_TYPE_AWAY, TRUE, can_have_message },
+ { "offline", TP_CONNECTION_PRESENCE_TYPE_OFFLINE, FALSE, NULL },
+ { "unknown", TP_CONNECTION_PRESENCE_TYPE_UNKNOWN, FALSE, NULL },
+ { "error", TP_CONNECTION_PRESENCE_TYPE_ERROR, FALSE, NULL },
+ { NULL }
+};
+
+static gboolean
+my_status_available (GObject *object,
+ guint index)
+{
+ TpBaseConnection *base = TP_BASE_CONNECTION (object);
+
+ if (base->status != TP_CONNECTION_STATUS_CONNECTED)
+ return FALSE;
+
+ return TRUE;
+}
+
+static GHashTable *
+my_get_contact_statuses (GObject *object,
+ const GArray *contacts,
+ GError **error)
+{
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (object);
+ GHashTable *result = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify) tp_presence_status_free);
+ guint i;
+
+ for (i = 0; i < contacts->len; i++)
+ {
+ TpHandle handle = g_array_index (contacts, TpHandle, i);
+ gpointer key = GUINT_TO_POINTER (handle);
+ TpTestsContactsConnectionPresenceStatusIndex index;
+ const gchar *presence_message;
+ GHashTable *parameters;
+
+ index = GPOINTER_TO_UINT (g_hash_table_lookup (
+ self->priv->presence_statuses, key));
+ presence_message = g_hash_table_lookup (
+ self->priv->presence_messages, key);
+
+ parameters = g_hash_table_new_full (g_str_hash,
+ g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free);
+
+ if (presence_message != NULL)
+ g_hash_table_insert (parameters, "message",
+ tp_g_value_slice_new_string (presence_message));
+
+ g_hash_table_insert (result, key,
+ tp_presence_status_new (index, parameters));
+ g_hash_table_unref (parameters);
+ }
+
+ return result;
+}
+
+static gboolean
+my_set_own_status (GObject *object,
+ const TpPresenceStatus *status,
+ GError **error)
+{
+ TpBaseConnection *base_conn = TP_BASE_CONNECTION (object);
+ TpTestsContactsConnectionPresenceStatusIndex index = status->index;
+ const gchar *message = "";
+
+ if (status->optional_arguments != NULL)
+ {
+ message = g_hash_table_lookup (status->optional_arguments, "message");
+
+ if (message == NULL)
+ message = "";
+ }
+
+ tp_tests_contacts_connection_change_presences (TP_TESTS_CONTACTS_CONNECTION (object),
+ 1, &(base_conn->self_handle), &index, &message);
+
+ return TRUE;
+}
+
+static guint
+my_get_maximum_status_message_length_cb (GObject *obj)
+{
+ return 512;
+}
+
+static GPtrArray *
+create_channel_managers (TpBaseConnection *conn)
+{
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (conn);
+ GPtrArray *ret = g_ptr_array_sized_new (1);
+
+ self->priv->list_manager = g_object_new (TP_TESTS_TYPE_CONTACT_LIST_MANAGER,
+ "connection", conn, NULL);
+
+ g_ptr_array_add (ret, self->priv->list_manager);
+
+ return ret;
+}
+
+static void
+tp_tests_contacts_connection_class_init (TpTestsContactsConnectionClass *klass)
+{
+ TpBaseConnectionClass *base_class =
+ (TpBaseConnectionClass *) klass;
+ GObjectClass *object_class = (GObjectClass *) klass;
+ TpPresenceMixinClass *mixin_class;
+ static const gchar *interfaces_always_present[] = {
+ TP_IFACE_CONNECTION_INTERFACE_ALIASING,
+ TP_IFACE_CONNECTION_INTERFACE_AVATARS,
+ TP_IFACE_CONNECTION_INTERFACE_CONTACTS,
+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_LIST,
+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_GROUPS,
+ TP_IFACE_CONNECTION_INTERFACE_PRESENCE,
+ TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE,
+ TP_IFACE_CONNECTION_INTERFACE_LOCATION,
+ TP_IFACE_CONNECTION_INTERFACE_CLIENT_TYPES,
+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES,
+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO,
+ TP_IFACE_CONNECTION_INTERFACE_REQUESTS,
+ NULL };
+ static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
+ { TP_IFACE_CONNECTION_INTERFACE_AVATARS,
+ conn_avatars_properties_getter,
+ NULL,
+ conn_avatars_properties,
+ },
+ { TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO,
+ conn_contact_info_properties_getter,
+ NULL,
+ conn_contact_info_properties,
+ },
+ { NULL }
+ };
+
+ object_class->constructed = constructed;
+ object_class->finalize = finalize;
+ g_type_class_add_private (klass, sizeof (TpTestsContactsConnectionPrivate));
+
+ base_class->interfaces_always_present = interfaces_always_present;
+ base_class->create_channel_managers = create_channel_managers;
+
+ tp_contacts_mixin_class_init (object_class,
+ G_STRUCT_OFFSET (TpTestsContactsConnectionClass, contacts_mixin));
+
+ tp_presence_mixin_class_init (object_class,
+ G_STRUCT_OFFSET (TpTestsContactsConnectionClass, presence_mixin),
+ my_status_available, my_get_contact_statuses,
+ my_set_own_status, my_statuses);
+ mixin_class = TP_PRESENCE_MIXIN_CLASS(klass);
+ mixin_class->get_maximum_status_message_length =
+ my_get_maximum_status_message_length_cb;
+
+ tp_presence_mixin_simple_presence_init_dbus_properties (object_class);
+
+ klass->properties_class.interfaces = prop_interfaces;
+ tp_dbus_properties_mixin_class_init (object_class,
+ G_STRUCT_OFFSET (TpTestsContactsConnectionClass, properties_class));
+
+ tp_base_contact_list_mixin_class_init (base_class);
+}
+
+TpTestsContactListManager *
+tp_tests_contacts_connection_get_contact_list_manager (
+ TpTestsContactsConnection *self)
+{
+ return self->priv->list_manager;
+}
+
+/**
+ * tp_tests_contacts_connection_change_aliases:
+ * @self: a #TpTestsContactsConnection
+ * @n: the number of handles
+ * @handles: (array length=n): the handles
+ * @aliases: (array zero-terminated=1): aliases
+ *
+ */
+void
+tp_tests_contacts_connection_change_aliases (TpTestsContactsConnection *self,
+ guint n,
+ const TpHandle *handles,
+ const gchar * const *aliases)
+{
+ GPtrArray *structs = g_ptr_array_sized_new (n);
+ guint i;
+
+ for (i = 0; i < n; i++)
+ {
+ GValueArray *pair = g_value_array_new (2);
+
+ DEBUG ("contact#%u -> %s", handles[i], aliases[i]);
+
+ g_hash_table_insert (self->priv->aliases,
+ GUINT_TO_POINTER (handles[i]), g_strdup (aliases[i]));
+
+ g_value_array_append (pair, NULL);
+ g_value_init (pair->values + 0, G_TYPE_UINT);
+ g_value_set_uint (pair->values + 0, handles[i]);
+
+ g_value_array_append (pair, NULL);
+ g_value_init (pair->values + 1, G_TYPE_STRING);
+ g_value_set_string (pair->values + 1, aliases[i]);
+
+ g_ptr_array_add (structs, pair);
+ }
+
+ tp_svc_connection_interface_aliasing_emit_aliases_changed (self,
+ structs);
+
+ g_ptr_array_foreach (structs, (GFunc) g_value_array_free, NULL);
+ g_ptr_array_unref (structs);
+}
+
+void
+tp_tests_contacts_connection_change_presences (
+ TpTestsContactsConnection *self,
+ guint n,
+ const TpHandle *handles,
+ const TpTestsContactsConnectionPresenceStatusIndex *indexes,
+ const gchar * const *messages)
+{
+ GHashTable *presences = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify) tp_presence_status_free);
+ guint i;
+
+ for (i = 0; i < n; i++)
+ {
+ GHashTable *parameters;
+ gpointer key = GUINT_TO_POINTER (handles[i]);
+
+ DEBUG ("contact#%u -> %s \"%s\"", handles[i],
+ my_statuses[indexes[i]].name, messages[i]);
+
+ g_hash_table_insert (self->priv->presence_statuses, key,
+ GUINT_TO_POINTER (indexes[i]));
+ g_hash_table_insert (self->priv->presence_messages, key,
+ g_strdup (messages[i]));
+
+ parameters = g_hash_table_new_full (g_str_hash,
+ g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free);
+
+ if (messages[i] != NULL && messages[i][0] != '\0')
+ g_hash_table_insert (parameters, "message",
+ tp_g_value_slice_new_string (messages[i]));
+
+ g_hash_table_insert (presences, key, tp_presence_status_new (indexes[i],
+ parameters));
+ g_hash_table_unref (parameters);
+ }
+
+ tp_presence_mixin_emit_presence_update ((GObject *) self,
+ presences);
+ g_hash_table_unref (presences);
+}
+
+void
+tp_tests_contacts_connection_change_avatar_tokens (TpTestsContactsConnection *self,
+ guint n,
+ const TpHandle *handles,
+ const gchar * const *tokens)
+{
+ guint i;
+
+ for (i = 0; i < n; i++)
+ {
+ DEBUG ("contact#%u -> %s", handles[i], tokens[i]);
+ g_hash_table_insert (self->priv->avatars,
+ GUINT_TO_POINTER (handles[i]), avatar_data_new (NULL, NULL, tokens[i]));
+ tp_svc_connection_interface_avatars_emit_avatar_updated (self,
+ handles[i], tokens[i]);
+ }
+}
+
+void
+tp_tests_contacts_connection_change_avatar_data (
+ TpTestsContactsConnection *self,
+ TpHandle handle,
+ GArray *data,
+ const gchar *mime_type,
+ const gchar *token)
+{
+ g_hash_table_insert (self->priv->avatars,
+ GUINT_TO_POINTER (handle), avatar_data_new (data, mime_type, token));
+
+ tp_svc_connection_interface_avatars_emit_avatar_updated (self,
+ handle, token);
+}
+
+void
+tp_tests_contacts_connection_change_locations (TpTestsContactsConnection *self,
+ guint n,
+ const TpHandle *handles,
+ GHashTable **locations)
+{
+ guint i;
+
+ for (i = 0; i < n; i++)
+ {
+ DEBUG ("contact#%u ->", handles[i]);
+ tp_asv_dump (locations[i]);
+ g_hash_table_insert (self->priv->locations,
+ GUINT_TO_POINTER (handles[i]), g_hash_table_ref (locations[i]));
+
+ tp_svc_connection_interface_location_emit_location_updated (self,
+ handles[i], locations[i]);
+ }
+}
+
+void
+tp_tests_contacts_connection_change_capabilities (
+ TpTestsContactsConnection *self,
+ GHashTable *capabilities)
+{
+ GHashTableIter iter;
+ gpointer handle, caps;
+
+ g_hash_table_iter_init (&iter, capabilities);
+ while (g_hash_table_iter_next (&iter, &handle, &caps))
+ {
+ g_hash_table_insert (self->priv->capabilities,
+ handle,
+ g_boxed_copy (TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST,
+ caps));
+ }
+
+ tp_svc_connection_interface_contact_capabilities_emit_contact_capabilities_changed (
+ self, capabilities);
+}
+
+void
+tp_tests_contacts_connection_change_contact_info (
+ TpTestsContactsConnection *self,
+ TpHandle handle,
+ GPtrArray *info)
+{
+ g_hash_table_insert (self->priv->contact_info, GUINT_TO_POINTER (handle),
+ g_ptr_array_ref (info));
+
+ tp_svc_connection_interface_contact_info_emit_contact_info_changed (self,
+ handle, info);
+}
+
+void
+tp_tests_contacts_connection_set_default_contact_info (
+ TpTestsContactsConnection *self,
+ GPtrArray *info)
+{
+ if (self->priv->default_contact_info != NULL)
+ g_ptr_array_unref (self->priv->default_contact_info);
+ self->priv->default_contact_info = g_ptr_array_ref (info);
+}
+
+static void
+my_get_alias_flags (TpSvcConnectionInterfaceAliasing *aliasing,
+ DBusGMethodInvocation *context)
+{
+ TpBaseConnection *base = TP_BASE_CONNECTION (aliasing);
+
+ TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+ tp_svc_connection_interface_aliasing_return_from_get_alias_flags (context,
+ 0);
+}
+
+static void
+my_get_aliases (TpSvcConnectionInterfaceAliasing *aliasing,
+ const GArray *contacts,
+ DBusGMethodInvocation *context)
+{
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (aliasing);
+ TpBaseConnection *base = TP_BASE_CONNECTION (aliasing);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base,
+ TP_HANDLE_TYPE_CONTACT);
+ GHashTable *result;
+ GError *error = NULL;
+ guint i;
+
+ TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+ if (!tp_handles_are_valid (contact_repo, contacts, FALSE, &error))
+ {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return;
+ }
+
+ result = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
+
+ for (i = 0; i < contacts->len; i++)
+ {
+ TpHandle handle = g_array_index (contacts, TpHandle, i);
+ const gchar *alias = g_hash_table_lookup (self->priv->aliases,
+ GUINT_TO_POINTER (handle));
+
+ if (alias == NULL)
+ g_hash_table_insert (result, GUINT_TO_POINTER (handle),
+ (gchar *) tp_handle_inspect (contact_repo, handle));
+ else
+ g_hash_table_insert (result, GUINT_TO_POINTER (handle),
+ (gchar *) alias);
+ }
+
+ tp_svc_connection_interface_aliasing_return_from_get_aliases (context,
+ result);
+ g_hash_table_unref (result);
+}
+
+static void
+my_request_aliases (TpSvcConnectionInterfaceAliasing *aliasing,
+ const GArray *contacts,
+ DBusGMethodInvocation *context)
+{
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (aliasing);
+ TpBaseConnection *base = TP_BASE_CONNECTION (aliasing);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base,
+ TP_HANDLE_TYPE_CONTACT);
+ GPtrArray *result;
+ gchar **strings;
+ GError *error = NULL;
+ guint i;
+
+ TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+ if (!tp_handles_are_valid (contact_repo, contacts, FALSE, &error))
+ {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return;
+ }
+
+ result = g_ptr_array_sized_new (contacts->len + 1);
+
+ for (i = 0; i < contacts->len; i++)
+ {
+ TpHandle handle = g_array_index (contacts, TpHandle, i);
+ const gchar *alias = g_hash_table_lookup (self->priv->aliases,
+ GUINT_TO_POINTER (handle));
+
+ if (alias == NULL)
+ g_ptr_array_add (result,
+ (gchar *) tp_handle_inspect (contact_repo, handle));
+ else
+ g_ptr_array_add (result, (gchar *) alias);
+ }
+
+ g_ptr_array_add (result, NULL);
+ strings = (gchar **) g_ptr_array_free (result, FALSE);
+ tp_svc_connection_interface_aliasing_return_from_request_aliases (context,
+ (const gchar **) strings);
+ g_free (strings);
+}
+
+static void
+init_aliasing (gpointer g_iface,
+ gpointer iface_data)
+{
+ TpSvcConnectionInterfaceAliasingClass *klass = g_iface;
+
+#define IMPLEMENT(x) tp_svc_connection_interface_aliasing_implement_##x (\
+ klass, my_##x)
+ IMPLEMENT(get_alias_flags);
+ IMPLEMENT(request_aliases);
+ IMPLEMENT(get_aliases);
+ /* IMPLEMENT(set_aliases); */
+#undef IMPLEMENT
+}
+
+static void
+my_get_avatar_tokens (TpSvcConnectionInterfaceAvatars *avatars,
+ const GArray *contacts,
+ DBusGMethodInvocation *context)
+{
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (avatars);
+ TpBaseConnection *base = TP_BASE_CONNECTION (avatars);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base,
+ TP_HANDLE_TYPE_CONTACT);
+ GError *error = NULL;
+ GHashTable *result;
+ guint i;
+
+ TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+ if (!tp_handles_are_valid (contact_repo, contacts, FALSE, &error))
+ {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return;
+ }
+
+ result = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
+
+ for (i = 0; i < contacts->len; i++)
+ {
+ TpHandle handle = g_array_index (contacts, TpHandle, i);
+ AvatarData *a = g_hash_table_lookup (self->priv->avatars,
+ GUINT_TO_POINTER (handle));
+
+ if (a == NULL || a->token == NULL)
+ {
+ /* we're expected to do a round-trip to the server to find out
+ * their token, so we have to give some sort of result. Assume
+ * no avatar, here */
+ a = avatar_data_new (NULL, NULL, "");
+ g_hash_table_insert (self->priv->avatars,
+ GUINT_TO_POINTER (handle), a);
+ tp_svc_connection_interface_avatars_emit_avatar_updated (self,
+ handle, a->token);
+ }
+
+ g_hash_table_insert (result, GUINT_TO_POINTER (handle),
+ a->token);
+ }
+
+ tp_svc_connection_interface_avatars_return_from_get_known_avatar_tokens (
+ context, result);
+ g_hash_table_unref (result);
+}
+
+static void
+my_get_known_avatar_tokens (TpSvcConnectionInterfaceAvatars *avatars,
+ const GArray *contacts,
+ DBusGMethodInvocation *context)
+{
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (avatars);
+ TpBaseConnection *base = TP_BASE_CONNECTION (avatars);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base,
+ TP_HANDLE_TYPE_CONTACT);
+ GError *error = NULL;
+ GHashTable *result;
+ guint i;
+
+ TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+ if (!tp_handles_are_valid (contact_repo, contacts, FALSE, &error))
+ {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return;
+ }
+
+ result = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
+
+ for (i = 0; i < contacts->len; i++)
+ {
+ TpHandle handle = g_array_index (contacts, TpHandle, i);
+ AvatarData *a = g_hash_table_lookup (self->priv->avatars,
+ GUINT_TO_POINTER (handle));
+ const gchar *token = a ? a->token : NULL;
+
+ g_hash_table_insert (result, GUINT_TO_POINTER (handle),
+ (gchar *) (token != NULL ? token : ""));
+ }
+
+ tp_svc_connection_interface_avatars_return_from_get_known_avatar_tokens (
+ context, result);
+ g_hash_table_unref (result);
+}
+
+static void
+my_request_avatars (TpSvcConnectionInterfaceAvatars *avatars,
+ const GArray *contacts,
+ DBusGMethodInvocation *context)
+{
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (avatars);
+ TpBaseConnection *base = TP_BASE_CONNECTION (avatars);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base,
+ TP_HANDLE_TYPE_CONTACT);
+ GError *error = NULL;
+ guint i;
+
+ TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+ if (!tp_handles_are_valid (contact_repo, contacts, FALSE, &error))
+ {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return;
+ }
+
+ for (i = 0; i < contacts->len; i++)
+ {
+ TpHandle handle = g_array_index (contacts, TpHandle, i);
+ AvatarData *a = g_hash_table_lookup (self->priv->avatars,
+ GUINT_TO_POINTER (handle));
+
+ if (a != NULL)
+ tp_svc_connection_interface_avatars_emit_avatar_retrieved (self, handle,
+ a->token, a->data, a->mime_type);
+ }
+
+ tp_svc_connection_interface_avatars_return_from_request_avatars (context);
+}
+
+static void
+conn_avatars_properties_getter (GObject *object,
+ GQuark interface,
+ GQuark name,
+ GValue *value,
+ gpointer getter_data)
+{
+ GQuark q_mime_types = g_quark_from_static_string (
+ "SupportedAvatarMIMETypes");
+
+ if (name == q_mime_types)
+ {
+ g_value_set_static_boxed (value, mime_types);
+ }
+ else
+ {
+ g_value_set_uint (value, GPOINTER_TO_UINT (getter_data));
+ }
+}
+
+static void
+init_avatars (gpointer g_iface,
+ gpointer iface_data)
+{
+ TpSvcConnectionInterfaceAvatarsClass *klass = g_iface;
+
+#define IMPLEMENT(x) tp_svc_connection_interface_avatars_implement_##x (\
+ klass, my_##x)
+ /* IMPLEMENT(get_avatar_requirements); */
+ IMPLEMENT(get_avatar_tokens);
+ IMPLEMENT(get_known_avatar_tokens);
+ /* IMPLEMENT(request_avatar); */
+ IMPLEMENT(request_avatars);
+ /* IMPLEMENT(set_avatar); */
+ /* IMPLEMENT(clear_avatar); */
+#undef IMPLEMENT
+}
+
+static void
+my_get_locations (TpSvcConnectionInterfaceLocation *avatars,
+ const GArray *contacts,
+ DBusGMethodInvocation *context)
+{
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (avatars);
+ TpBaseConnection *base = TP_BASE_CONNECTION (avatars);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base,
+ TP_HANDLE_TYPE_CONTACT);
+ GError *error = NULL;
+ GHashTable *result;
+ guint i;
+
+ TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+ if (!tp_handles_are_valid (contact_repo, contacts, FALSE, &error))
+ {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return;
+ }
+
+ result = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
+
+ for (i = 0; i < contacts->len; i++)
+ {
+ TpHandle handle = g_array_index (contacts, TpHandle, i);
+ GHashTable *location = g_hash_table_lookup (self->priv->locations,
+ GUINT_TO_POINTER (handle));
+
+ if (location != NULL)
+ {
+ g_hash_table_insert (result, GUINT_TO_POINTER (handle), location);
+ }
+ }
+
+ tp_svc_connection_interface_location_return_from_get_locations (
+ context, result);
+ g_hash_table_unref (result);
+}
+
+static void
+init_location (gpointer g_iface,
+ gpointer iface_data)
+{
+ TpSvcConnectionInterfaceLocationClass *klass = g_iface;
+
+#define IMPLEMENT(x) tp_svc_connection_interface_location_implement_##x (\
+ klass, my_##x)
+ IMPLEMENT(get_locations);
+#undef IMPLEMENT
+}
+
+static void
+my_get_contact_capabilities (TpSvcConnectionInterfaceContactCapabilities *obj,
+ const GArray *contacts,
+ DBusGMethodInvocation *context)
+{
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (obj);
+ TpBaseConnection *base = TP_BASE_CONNECTION (obj);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base,
+ TP_HANDLE_TYPE_CONTACT);
+ GError *error = NULL;
+ GHashTable *result;
+ guint i;
+
+ TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+ if (!tp_handles_are_valid (contact_repo, contacts, FALSE, &error))
+ {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return;
+ }
+
+ result = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
+
+ for (i = 0; i < contacts->len; i++)
+ {
+ TpHandle handle = g_array_index (contacts, TpHandle, i);
+ GPtrArray *arr = g_hash_table_lookup (self->priv->capabilities,
+ GUINT_TO_POINTER (handle));
+
+ if (arr != NULL)
+ {
+ g_hash_table_insert (result, GUINT_TO_POINTER (handle), arr);
+ }
+ }
+
+ tp_svc_connection_interface_contact_capabilities_return_from_get_contact_capabilities (
+ context, result);
+
+ g_hash_table_unref (result);
+}
+
+static void
+init_contact_caps (gpointer g_iface,
+ gpointer iface_data)
+{
+ TpSvcConnectionInterfaceContactCapabilitiesClass *klass = g_iface;
+
+#define IMPLEMENT(x) tp_svc_connection_interface_contact_capabilities_implement_##x (\
+ klass, my_##x)
+ IMPLEMENT(get_contact_capabilities);
+#undef IMPLEMENT
+}
+
+static GPtrArray *
+lookup_contact_info (TpTestsContactsConnection *self,
+ TpHandle handle)
+{
+ GPtrArray *ret = g_hash_table_lookup (self->priv->contact_info,
+ GUINT_TO_POINTER (handle));
+
+ if (ret == NULL && self->priv->default_contact_info != NULL)
+ {
+ ret = self->priv->default_contact_info;
+ g_hash_table_insert (self->priv->contact_info, GUINT_TO_POINTER (handle),
+ g_ptr_array_ref (ret));
+ }
+
+ if (ret == NULL)
+ return g_ptr_array_new ();
+
+ return g_ptr_array_ref (ret);
+}
+
+static void
+my_refresh_contact_info (TpSvcConnectionInterfaceContactInfo *obj,
+ const GArray *contacts,
+ DBusGMethodInvocation *context)
+{
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (obj);
+ TpBaseConnection *base = TP_BASE_CONNECTION (obj);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base,
+ TP_HANDLE_TYPE_CONTACT);
+ GError *error = NULL;
+ guint i;
+
+ TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+ if (!tp_handles_are_valid (contact_repo, contacts, FALSE, &error))
+ {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return;
+ }
+
+ for (i = 0; i < contacts->len; i++)
+ {
+ TpHandle handle = g_array_index (contacts, guint, i);
+ GPtrArray *arr = lookup_contact_info (self, handle);
+
+ tp_svc_connection_interface_contact_info_emit_contact_info_changed (self,
+ handle, arr);
+ g_ptr_array_unref (arr);
+ }
+
+ tp_svc_connection_interface_contact_info_return_from_refresh_contact_info (
+ context);
+}
+
+static void
+my_request_contact_info (TpSvcConnectionInterfaceContactInfo *obj,
+ guint handle,
+ DBusGMethodInvocation *context)
+{
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (obj);
+ TpBaseConnection *base = TP_BASE_CONNECTION (obj);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base,
+ TP_HANDLE_TYPE_CONTACT);
+ GError *error = NULL;
+ GPtrArray *ret;
+
+ TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+ if (!tp_handle_is_valid (contact_repo, handle, &error))
+ {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return;
+ }
+
+ ret = lookup_contact_info (self, handle);
+
+ tp_svc_connection_interface_contact_info_return_from_request_contact_info (
+ context, ret);
+
+ g_ptr_array_unref (ret);
+}
+
+static void
+my_set_contact_info (TpSvcConnectionInterfaceContactInfo *obj,
+ const GPtrArray *info,
+ DBusGMethodInvocation *context)
+{
+ TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (obj);
+ TpBaseConnection *base = TP_BASE_CONNECTION (obj);
+ GPtrArray *copy;
+ guint i;
+ TpHandle self_handle;
+
+ TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+ /* Deep copy info */
+ copy = g_ptr_array_new_with_free_func ((GDestroyNotify) g_value_array_free);
+ for (i = 0; i < info->len; i++)
+ g_ptr_array_add (copy, g_value_array_copy (g_ptr_array_index (info, i)));
+
+ self_handle = tp_base_connection_get_self_handle (base);
+ tp_tests_contacts_connection_change_contact_info (self, self_handle, copy);
+ g_ptr_array_unref (copy);
+
+ tp_svc_connection_interface_contact_info_return_from_set_contact_info (
+ context);
+}
+
+static void
+init_contact_info (gpointer g_iface,
+ gpointer iface_data)
+{
+ TpSvcConnectionInterfaceContactInfoClass *klass = g_iface;
+
+#define IMPLEMENT(x) tp_svc_connection_interface_contact_info_implement_##x (\
+ klass, my_##x)
+ IMPLEMENT (refresh_contact_info);
+ IMPLEMENT (request_contact_info);
+ IMPLEMENT (set_contact_info);
+#undef IMPLEMENT
+}
+
+/* =============== Legacy version (no Contacts interface) ================= */
+
+G_DEFINE_TYPE (TpTestsLegacyContactsConnection,
+ tp_tests_legacy_contacts_connection, TP_TESTS_TYPE_CONTACTS_CONNECTION);
+
+enum
+{
+ LEGACY_PROP_HAS_IMMORTAL_HANDLES = 1
+};
+
+static void
+legacy_contacts_connection_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ case LEGACY_PROP_HAS_IMMORTAL_HANDLES:
+ /* Pretend we don't. */
+ g_value_set_boolean (value, FALSE);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+tp_tests_legacy_contacts_connection_init (TpTestsLegacyContactsConnection *self)
+{
+}
+
+static void
+tp_tests_legacy_contacts_connection_class_init (
+ TpTestsLegacyContactsConnectionClass *klass)
+{
+ /* Leave Contacts out of the interfaces we say are present, so clients
+ * won't use it */
+ static const gchar *interfaces_always_present[] = {
+ TP_IFACE_CONNECTION_INTERFACE_ALIASING,
+ TP_IFACE_CONNECTION_INTERFACE_AVATARS,
+ TP_IFACE_CONNECTION_INTERFACE_PRESENCE,
+ TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE,
+ TP_IFACE_CONNECTION_INTERFACE_LOCATION,
+ TP_IFACE_CONNECTION_INTERFACE_REQUESTS,
+ NULL };
+ TpBaseConnectionClass *base_class =
+ (TpBaseConnectionClass *) klass;
+ GObjectClass *object_class = (GObjectClass *) klass;
+
+ object_class->get_property = legacy_contacts_connection_get_property;
+
+ base_class->interfaces_always_present = interfaces_always_present;
+
+ g_object_class_override_property (object_class,
+ LEGACY_PROP_HAS_IMMORTAL_HANDLES, "has-immortal-handles");
+}
+
+/* =============== No Requests and no ContactCapabilities ================= */
+
+G_DEFINE_TYPE (TpTestsNoRequestsConnection, tp_tests_no_requests_connection,
+ TP_TESTS_TYPE_CONTACTS_CONNECTION);
+
+static void
+tp_tests_no_requests_connection_init (TpTestsNoRequestsConnection *self)
+{
+}
+
+static void
+tp_tests_no_requests_connection_class_init (
+ TpTestsNoRequestsConnectionClass *klass)
+{
+ static const gchar *interfaces_always_present[] = {
+ TP_IFACE_CONNECTION_INTERFACE_ALIASING,
+ TP_IFACE_CONNECTION_INTERFACE_AVATARS,
+ TP_IFACE_CONNECTION_INTERFACE_CONTACTS,
+ TP_IFACE_CONNECTION_INTERFACE_PRESENCE,
+ TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE,
+ TP_IFACE_CONNECTION_INTERFACE_LOCATION,
+ NULL };
+ TpBaseConnectionClass *base_class =
+ (TpBaseConnectionClass *) klass;
+
+ base_class->interfaces_always_present = interfaces_always_present;
+ base_class->create_channel_managers = NULL;
+}
diff --git a/tests/lib/telepathy/contactlist/contacts-conn.h b/tests/lib/telepathy/contactlist/contacts-conn.h
new file mode 100644
index 0000000..64056e0
--- /dev/null
+++ b/tests/lib/telepathy/contactlist/contacts-conn.h
@@ -0,0 +1,190 @@
+/*
+ * contacts-conn.h - header for a connection with contact info
+ *
+ * Copyright (C) 2007-2008 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright (C) 2007-2008 Nokia Corporation
+ *
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved.
+ */
+
+#ifndef __TP_TESTS_CONTACTS_CONN_H__
+#define __TP_TESTS_CONTACTS_CONN_H__
+
+#include <glib-object.h>
+#include <telepathy-glib/base-connection.h>
+#include <telepathy-glib/contacts-mixin.h>
+#include <telepathy-glib/presence-mixin.h>
+
+#include "simple-conn.h"
+#include "contact-list-manager.h"
+
+G_BEGIN_DECLS
+
+typedef struct _TpTestsContactsConnection TpTestsContactsConnection;
+typedef struct _TpTestsContactsConnectionClass TpTestsContactsConnectionClass;
+typedef struct _TpTestsContactsConnectionPrivate TpTestsContactsConnectionPrivate;
+
+struct _TpTestsContactsConnectionClass {
+ TpTestsSimpleConnectionClass parent_class;
+
+ TpPresenceMixinClass presence_mixin;
+ TpContactsMixinClass contacts_mixin;
+ TpDBusPropertiesMixinClass properties_class;
+
+ TpContactsMixinFillContactAttributesFunc fill_client_types;
+};
+
+struct _TpTestsContactsConnection {
+ TpTestsSimpleConnection parent;
+
+ TpPresenceMixin presence_mixin;
+ TpContactsMixin contacts_mixin;
+
+ TpTestsContactsConnectionPrivate *priv;
+};
+
+GType tp_tests_contacts_connection_get_type (void);
+
+/* Must match my_statuses in the .c */
+typedef enum {
+ TP_TESTS_CONTACTS_CONNECTION_STATUS_AVAILABLE,
+ TP_TESTS_CONTACTS_CONNECTION_STATUS_BUSY,
+ TP_TESTS_CONTACTS_CONNECTION_STATUS_AWAY,
+ TP_TESTS_CONTACTS_CONNECTION_STATUS_OFFLINE,
+ TP_TESTS_CONTACTS_CONNECTION_STATUS_UNKNOWN,
+ TP_TESTS_CONTACTS_CONNECTION_STATUS_ERROR
+} TpTestsContactsConnectionPresenceStatusIndex;
+
+/* TYPE MACROS */
+#define TP_TESTS_TYPE_CONTACTS_CONNECTION \
+ (tp_tests_contacts_connection_get_type ())
+#define TP_TESTS_CONTACTS_CONNECTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_CONTACTS_CONNECTION, \
+ TpTestsContactsConnection))
+#define TP_TESTS_CONTACTS_CONNECTION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_CONTACTS_CONNECTION, \
+ TpTestsContactsConnectionClass))
+#define TP_TESTS_IS_CONTACTS_CONNECTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_CONTACTS_CONNECTION))
+#define TP_TESTS_IS_CONTACTS_CONNECTION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_CONTACTS_CONNECTION))
+#define TP_TESTS_CONTACTS_CONNECTION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_CONTACTS_CONNECTION, \
+ TpTestsContactsConnectionClass))
+
+TpTestsContactListManager *tp_tests_contacts_connection_get_contact_list_manager (
+ TpTestsContactsConnection *self);
+
+void tp_tests_contacts_connection_change_aliases (
+ TpTestsContactsConnection *self, guint n,
+ const TpHandle *handles, const gchar * const *aliases);
+
+void tp_tests_contacts_connection_change_presences (
+ TpTestsContactsConnection *self, guint n, const TpHandle *handles,
+ const TpTestsContactsConnectionPresenceStatusIndex *indexes,
+ const gchar * const *messages);
+
+void tp_tests_contacts_connection_change_avatar_tokens (
+ TpTestsContactsConnection *self, guint n, const TpHandle *handles,
+ const gchar * const *tokens);
+
+void tp_tests_contacts_connection_change_avatar_data (
+ TpTestsContactsConnection *self,
+ TpHandle handle,
+ GArray *data,
+ const gchar *mime_type,
+ const gchar *token);
+
+void tp_tests_contacts_connection_change_locations (
+ TpTestsContactsConnection *self,
+ guint n,
+ const TpHandle *handles,
+ GHashTable **locations);
+
+void tp_tests_contacts_connection_change_capabilities (
+ TpTestsContactsConnection *self, GHashTable *capabilities);
+
+void tp_tests_contacts_connection_change_contact_info (
+ TpTestsContactsConnection *self, TpHandle handle, GPtrArray *info);
+
+void tp_tests_contacts_connection_set_default_contact_info (
+ TpTestsContactsConnection *self,
+ GPtrArray *info);
+
+/* Legacy version (no Contacts interface, and no immortal handles) */
+
+typedef struct _TpTestsLegacyContactsConnection TpTestsLegacyContactsConnection;
+typedef struct _TpTestsLegacyContactsConnectionClass TpTestsLegacyContactsConnectionClass;
+typedef struct _TpTestsLegacyContactsConnectionPrivate
+ TpTestsLegacyContactsConnectionPrivate;
+
+struct _TpTestsLegacyContactsConnectionClass {
+ TpTestsContactsConnectionClass parent_class;
+};
+
+struct _TpTestsLegacyContactsConnection {
+ TpTestsContactsConnection parent;
+
+ TpTestsLegacyContactsConnectionPrivate *priv;
+};
+
+GType tp_tests_legacy_contacts_connection_get_type (void);
+
+/* TYPE MACROS */
+#define TP_TESTS_TYPE_LEGACY_CONTACTS_CONNECTION \
+ (tp_tests_legacy_contacts_connection_get_type ())
+#define LEGACY_TP_TESTS_CONTACTS_CONNECTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_LEGACY_CONTACTS_CONNECTION, \
+ TpTestsLegacyContactsConnection))
+#define LEGACY_TP_TESTS_CONTACTS_CONNECTION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_LEGACY_CONTACTS_CONNECTION, \
+ TpTestsLegacyContactsConnectionClass))
+#define TP_TESTS_LEGACY_CONTACTS_IS_CONNECTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_LEGACY_CONTACTS_CONNECTION))
+#define TP_TESTS_LEGACY_CONTACTS_IS_CONNECTION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_LEGACY_CONTACTS_CONNECTION))
+#define LEGACY_TP_TESTS_CONTACTS_CONNECTION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_LEGACY_CONTACTS_CONNECTION, \
+ TpTestsLegacyContactsConnectionClass))
+
+/* No Requests version */
+
+typedef struct _TpTestsNoRequestsConnection TpTestsNoRequestsConnection;
+typedef struct _TpTestsNoRequestsConnectionClass TpTestsNoRequestsConnectionClass;
+typedef struct _TpTestsNoRequestsConnectionPrivate
+ TpTestsNoRequestsConnectionPrivate;
+
+struct _TpTestsNoRequestsConnectionClass {
+ TpTestsContactsConnectionClass parent_class;
+};
+
+struct _TpTestsNoRequestsConnection {
+ TpTestsContactsConnection parent;
+
+ TpTestsNoRequestsConnectionPrivate *priv;
+};
+
+GType tp_tests_no_requests_connection_get_type (void);
+
+/* TYPE MACROS */
+#define TP_TESTS_TYPE_NO_REQUESTS_CONNECTION \
+ (tp_tests_no_requests_connection_get_type ())
+#define TP_TESTS_NO_REQUESTS_CONNECTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_NO_REQUESTS_CONNECTION, \
+ TpTestsNoRequestsConnection))
+#define TP_TESTS_NO_REQUESTS_CONNECTION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_NO_REQUESTS_CONNECTION, \
+ TpTestsNoRequestsConnectionClass))
+#define TP_TESTS_NO_REQUESTS_IS_CONNECTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_NO_REQUESTS_CONNECTION))
+#define TP_TESTS_NO_REQUESTS_IS_CONNECTION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_NO_REQUESTS_CONNECTION))
+#define TP_TESTS_NO_REQUESTS_CONNECTION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_NO_REQUESTS_CONNECTION, \
+ TpTestsNoRequestsConnectionClass))
+
+G_END_DECLS
+
+#endif /* ifndef __TP_TESTS_CONTACTS_CONN_H__ */
diff --git a/tests/lib/telepathy/contactlist/debug.h b/tests/lib/telepathy/contactlist/debug.h
new file mode 100644
index 0000000..60e070b
--- /dev/null
+++ b/tests/lib/telepathy/contactlist/debug.h
@@ -0,0 +1,3 @@
+#undef DEBUG
+#define DEBUG(format, ...) \
+ g_debug ("%s: " format, G_STRFUNC, ##__VA_ARGS__)
diff --git a/tests/lib/telepathy/contactlist/account-manager.c b/tests/lib/telepathy/contactlist/simple-account-manager.c
similarity index 54%
rename from tests/lib/telepathy/contactlist/account-manager.c
rename to tests/lib/telepathy/contactlist/simple-account-manager.c
index e8e12b5..8df364a 100644
--- a/tests/lib/telepathy/contactlist/account-manager.c
+++ b/tests/lib/telepathy/contactlist/simple-account-manager.c
@@ -1,27 +1,28 @@
/*
- * account-manager.c - a simple account manager service.
+ * simple-account-manager.c - a simple account manager service.
*
- * Copyright (C) 2007-2009 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright (C) 2007-2012 Collabora Ltd. <http://www.collabora.co.uk/>
* Copyright (C) 2007-2008 Nokia Corporation
*
* Copying and distribution of this file, with or without modification,
* are permitted in any medium without royalty provided the copyright
* notice and this notice are preserved.
- *
- * Copied from telepathy-glib/tests/lib/simple-account-manager.c.
*/
-#include "account-manager.h"
+#include "config.h"
+
+#include "simple-account-manager.h"
#include <telepathy-glib/gtypes.h>
#include <telepathy-glib/interfaces.h>
#include <telepathy-glib/svc-generic.h>
#include <telepathy-glib/svc-account-manager.h>
+#include <telepathy-glib/util.h>
static void account_manager_iface_init (gpointer, gpointer);
-G_DEFINE_TYPE_WITH_CODE (TpTestsAccountManager,
- tp_tests_account_manager,
+G_DEFINE_TYPE_WITH_CODE (TpTestsSimpleAccountManager,
+ tp_tests_simple_account_manager,
G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_ACCOUNT_MANAGER,
account_manager_iface_init);
@@ -33,10 +34,6 @@ G_DEFINE_TYPE_WITH_CODE (TpTestsAccountManager,
/* TP_IFACE_ACCOUNT_MANAGER is implied */
static const char *ACCOUNT_MANAGER_INTERFACES[] = { NULL };
-static const gchar *INVALID_ACCOUNTS[] = {
- "/org/freedesktop/Telepathy/Account/fakecm/fakeproto/invalidaccount",
- NULL };
-
enum
{
PROP_0,
@@ -45,13 +42,14 @@ enum
PROP_INVALID_ACCOUNTS,
};
-struct _TpTestsAccountManagerPrivate
+struct _TpTestsSimpleAccountManagerPrivate
{
GPtrArray *valid_accounts;
+ GPtrArray *invalid_accounts;
};
static void
-tp_tests_account_manager_create_account (TpSvcAccountManager *self,
+tp_tests_simple_account_manager_create_account (TpSvcAccountManager *self,
const gchar *in_Connection_Manager,
const gchar *in_Protocol,
const gchar *in_Display_Name,
@@ -69,39 +67,29 @@ account_manager_iface_init (gpointer klass,
gpointer unused G_GNUC_UNUSED)
{
#define IMPLEMENT(x) tp_svc_account_manager_implement_##x (\
- klass, tp_tests_account_manager_##x)
+ klass, tp_tests_simple_account_manager_##x)
IMPLEMENT (create_account);
#undef IMPLEMENT
}
static void
-tp_tests_account_manager_init (TpTestsAccountManager *self)
+tp_tests_simple_account_manager_init (TpTestsSimpleAccountManager *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- TP_TESTS_TYPE_ACCOUNT_MANAGER, TpTestsAccountManagerPrivate);
-
- self->priv->valid_accounts =
- g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
-}
-
-static void
-tp_tests_account_manager_finalize (GObject *obj)
-{
- g_ptr_array_free (TP_TESTS_ACCOUNT_MANAGER (obj)->priv->valid_accounts, TRUE);
+ TP_TESTS_TYPE_SIMPLE_ACCOUNT_MANAGER, TpTestsSimpleAccountManagerPrivate);
- G_OBJECT_CLASS (tp_tests_account_manager_parent_class)->finalize (obj);
+ self->priv->valid_accounts = g_ptr_array_new_with_free_func (g_free);
+ self->priv->invalid_accounts = g_ptr_array_new_with_free_func (g_free);
}
static void
-tp_tests_account_manager_get_property (GObject *object,
+tp_tests_simple_account_manager_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *spec)
{
- TpTestsAccountManagerPrivate *priv = TP_TESTS_ACCOUNT_MANAGER (object)->priv;
- GPtrArray *accounts;
- guint i = 0;
+ TpTestsSimpleAccountManager *self = SIMPLE_ACCOUNT_MANAGER (object);
switch (property_id) {
case PROP_INTERFACES:
@@ -109,21 +97,11 @@ tp_tests_account_manager_get_property (GObject *object,
break;
case PROP_VALID_ACCOUNTS:
- accounts = g_ptr_array_new ();
-
- for (i = 0; i < priv->valid_accounts->len; i++)
- g_ptr_array_add (accounts, g_strdup (priv->valid_accounts->pdata[i]));
-
- g_value_take_boxed (value, accounts);
+ g_value_set_boxed (value, self->priv->valid_accounts);
break;
case PROP_INVALID_ACCOUNTS:
- accounts = g_ptr_array_new ();
-
- for (i=0; INVALID_ACCOUNTS[i] != NULL; i++)
- g_ptr_array_add (accounts, g_strdup (INVALID_ACCOUNTS[i]));
-
- g_value_take_boxed (value, accounts);
+ g_value_set_boxed (value, self->priv->invalid_accounts);
break;
default:
@@ -132,6 +110,18 @@ tp_tests_account_manager_get_property (GObject *object,
}
}
+static void
+tp_tests_simple_account_manager_finalize (GObject *object)
+{
+ TpTestsSimpleAccountManager *self = SIMPLE_ACCOUNT_MANAGER (object);
+
+ g_ptr_array_unref (self->priv->valid_accounts);
+ g_ptr_array_unref (self->priv->invalid_accounts);
+
+ G_OBJECT_CLASS (tp_tests_simple_account_manager_parent_class)->finalize (
+ object);
+}
+
/**
* This class currently only provides the minimum for
* tp_account_manager_prepare to succeed. This turns out to be only a working
@@ -140,18 +130,18 @@ tp_tests_account_manager_get_property (GObject *object,
* too.
*/
static void
-tp_tests_account_manager_class_init (
- TpTestsAccountManagerClass *klass)
+tp_tests_simple_account_manager_class_init (
+ TpTestsSimpleAccountManagerClass *klass)
{
GObjectClass *object_class = (GObjectClass *) klass;
GParamSpec *param_spec;
static TpDBusPropertiesMixinPropImpl am_props[] = {
- { "Interfaces", (gpointer) "interfaces", NULL },
- { "ValidAccounts", (gpointer) "valid-accounts", NULL },
- { "InvalidAccounts", (gpointer) "invalid-accounts", NULL },
+ { "Interfaces", "interfaces", NULL },
+ { "ValidAccounts", "valid-accounts", NULL },
+ { "InvalidAccounts", "invalid-accounts", NULL },
/*
- { "SupportedAccountProperties", (gpointer) "supported-account-properties", NULL },
+ { "SupportedAccountProperties", "supported-account-properties", NULL },
*/
{ NULL }
};
@@ -165,9 +155,9 @@ tp_tests_account_manager_class_init (
{ NULL },
};
- g_type_class_add_private (klass, sizeof (TpTestsAccountManagerPrivate));
- object_class->get_property = tp_tests_account_manager_get_property;
- object_class->finalize = tp_tests_account_manager_finalize;
+ g_type_class_add_private (klass, sizeof (TpTestsSimpleAccountManagerPrivate));
+ object_class->finalize = tp_tests_simple_account_manager_finalize;
+ object_class->get_property = tp_tests_simple_account_manager_get_property;
param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces",
"In this case we only implement AccountManager, so none.",
@@ -187,40 +177,46 @@ tp_tests_account_manager_class_init (
klass->dbus_props_class.interfaces = prop_interfaces;
tp_dbus_properties_mixin_class_init (object_class,
- G_STRUCT_OFFSET (TpTestsAccountManagerClass, dbus_props_class));
+ G_STRUCT_OFFSET (TpTestsSimpleAccountManagerClass, dbus_props_class));
}
-TpTestsAccountManager *
-tp_tests_account_manager_new (void)
+static void
+remove_from_array (GPtrArray *array, const gchar *str)
{
- return g_object_new (TP_TESTS_TYPE_ACCOUNT_MANAGER, NULL);
+ guint i;
+
+ for (i = 0; i < array->len; i++)
+ if (!tp_strdiff (str, g_ptr_array_index (array, i)))
+ {
+ g_ptr_array_remove_index_fast (array, i);
+ return;
+ }
}
void
-tp_tests_account_manager_add_account (TpTestsAccountManager *self,
- const gchar *account_path)
+tp_tests_simple_account_manager_add_account (
+ TpTestsSimpleAccountManager *self,
+ const gchar *object_path,
+ gboolean valid)
{
- g_ptr_array_add (self->priv->valid_accounts, g_strdup (account_path));
- tp_svc_account_manager_emit_account_validity_changed (self, account_path, TRUE);
- g_object_notify (G_OBJECT (self), "valid-accounts");
+ remove_from_array (self->priv->valid_accounts, object_path);
+ remove_from_array (self->priv->valid_accounts, object_path);
+
+ if (valid)
+ g_ptr_array_add (self->priv->valid_accounts, g_strdup (object_path));
+ else
+ g_ptr_array_add (self->priv->invalid_accounts, g_strdup (object_path));
+
+ tp_svc_account_manager_emit_account_validity_changed (self, object_path, valid);
}
void
-tp_tests_account_manager_remove_account (TpTestsAccountManager *self,
- const gchar *account_path)
+tp_tests_simple_account_manager_remove_account (
+ TpTestsSimpleAccountManager *self,
+ const gchar *object_path)
{
- TpTestsAccountManagerPrivate *priv = self->priv;
- guint i;
+ remove_from_array (self->priv->valid_accounts, object_path);
+ remove_from_array (self->priv->valid_accounts, object_path);
- for (i = 0; i < priv->valid_accounts->len; i++)
- {
- if (g_strcmp0 (account_path, priv->valid_accounts->pdata[0]) == 0)
- {
- g_ptr_array_remove_index_fast (priv->valid_accounts, i);
- break;
- }
- }
-
- g_object_notify (G_OBJECT (self), "valid-accounts");
- tp_svc_account_manager_emit_account_removed (self, account_path);
+ tp_svc_account_manager_emit_account_removed (self, object_path);
}
diff --git a/tests/lib/telepathy/contactlist/simple-account-manager.h b/tests/lib/telepathy/contactlist/simple-account-manager.h
new file mode 100644
index 0000000..c34a6bf
--- /dev/null
+++ b/tests/lib/telepathy/contactlist/simple-account-manager.h
@@ -0,0 +1,66 @@
+/*
+ * simple-account-manager.h - header for a simple account manager service.
+ *
+ * Copyright (C) 2007-2012 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright (C) 2007-2008 Nokia Corporation
+ *
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved.
+ */
+
+#ifndef __TP_TESTS_SIMPLE_ACCOUNT_MANAGER_H__
+#define __TP_TESTS_SIMPLE_ACCOUNT_MANAGER_H__
+
+#include <glib-object.h>
+#include <telepathy-glib/dbus-properties-mixin.h>
+
+
+G_BEGIN_DECLS
+
+typedef struct _TpTestsSimpleAccountManager TpTestsSimpleAccountManager;
+typedef struct _TpTestsSimpleAccountManagerClass TpTestsSimpleAccountManagerClass;
+typedef struct _TpTestsSimpleAccountManagerPrivate TpTestsSimpleAccountManagerPrivate;
+
+struct _TpTestsSimpleAccountManagerClass {
+ GObjectClass parent_class;
+ TpDBusPropertiesMixinClass dbus_props_class;
+};
+
+struct _TpTestsSimpleAccountManager {
+ GObject parent;
+
+ TpTestsSimpleAccountManagerPrivate *priv;
+};
+
+GType tp_tests_simple_account_manager_get_type (void);
+
+/* TYPE MACROS */
+#define TP_TESTS_TYPE_SIMPLE_ACCOUNT_MANAGER \
+ (tp_tests_simple_account_manager_get_type ())
+#define SIMPLE_ACCOUNT_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_SIMPLE_ACCOUNT_MANAGER, \
+ TpTestsSimpleAccountManager))
+#define SIMPLE_ACCOUNT_MANAGER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_SIMPLE_ACCOUNT_MANAGER, \
+ TpTestsSimpleAccountManagerClass))
+#define SIMPLE_IS_ACCOUNT_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_SIMPLE_ACCOUNT_MANAGER))
+#define SIMPLE_IS_ACCOUNT_MANAGER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_SIMPLE_ACCOUNT_MANAGER))
+#define SIMPLE_ACCOUNT_MANAGER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_SIMPLE_ACCOUNT_MANAGER, \
+ TpTestsSimpleAccountManagerClass))
+
+void tp_tests_simple_account_manager_add_account (
+ TpTestsSimpleAccountManager *self,
+ const gchar *object_path,
+ gboolean valid);
+
+void tp_tests_simple_account_manager_remove_account (
+ TpTestsSimpleAccountManager *self,
+ const gchar *object_path);
+
+G_END_DECLS
+
+#endif /* #ifndef __TP_TESTS_SIMPLE_ACCOUNT_MANAGER_H__ */
diff --git a/tests/lib/telepathy/contactlist/simple-account.c b/tests/lib/telepathy/contactlist/simple-account.c
new file mode 100644
index 0000000..934643d
--- /dev/null
+++ b/tests/lib/telepathy/contactlist/simple-account.c
@@ -0,0 +1,579 @@
+/*
+ * simple-account.c - a simple account service.
+ *
+ * Copyright (C) 2010-2012 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved.
+ */
+
+#include "config.h"
+
+#include "simple-account.h"
+
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/defs.h>
+#include <telepathy-glib/enums.h>
+#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/util.h>
+#include <telepathy-glib/svc-generic.h>
+#include <telepathy-glib/svc-account.h>
+
+static void account_iface_init (gpointer, gpointer);
+
+G_DEFINE_TYPE_WITH_CODE (TpTestsSimpleAccount,
+ tp_tests_simple_account,
+ G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_ACCOUNT,
+ account_iface_init);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_ACCOUNT_INTERFACE_AVATAR,
+ NULL);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_ACCOUNT_INTERFACE_ADDRESSING,
+ NULL);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_ACCOUNT_INTERFACE_STORAGE,
+ NULL);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
+ tp_dbus_properties_mixin_iface_init)
+ )
+
+/* TP_IFACE_ACCOUNT is implied */
+static const char *ACCOUNT_INTERFACES[] = {
+ TP_IFACE_ACCOUNT_INTERFACE_ADDRESSING,
+ TP_IFACE_ACCOUNT_INTERFACE_STORAGE,
+ NULL };
+
+enum
+{
+ PROP_0,
+ PROP_INTERFACES,
+ PROP_DISPLAY_NAME,
+ PROP_ICON,
+ PROP_VALID,
+ PROP_ENABLED,
+ PROP_NICKNAME,
+ PROP_PARAMETERS,
+ PROP_AUTOMATIC_PRESENCE,
+ PROP_CONNECT_AUTO,
+ PROP_CONNECTION,
+ PROP_CONNECTION_STATUS,
+ PROP_CONNECTION_STATUS_REASON,
+ PROP_CURRENT_PRESENCE,
+ PROP_REQUESTED_PRESENCE,
+ PROP_NORMALIZED_NAME,
+ PROP_HAS_BEEN_ONLINE,
+ PROP_URI_SCHEMES,
+ PROP_STORAGE_PROVIDER,
+ PROP_STORAGE_IDENTIFIER,
+ PROP_STORAGE_SPECIFIC_INFORMATION,
+ PROP_STORAGE_RESTRICTIONS,
+ PROP_AVATAR,
+ PROP_SUPERSEDES,
+ N_PROPS
+};
+
+struct _TpTestsSimpleAccountPrivate
+{
+ TpConnectionPresenceType presence;
+ gchar *presence_status;
+ gchar *presence_msg;
+ gchar *connection_path;
+ gboolean enabled;
+};
+
+static void
+tp_tests_simple_account_update_parameters (TpSvcAccount *svc,
+ GHashTable *parameters,
+ const gchar **unset_parameters,
+ DBusGMethodInvocation *context)
+{
+ GPtrArray *reconnect_required = g_ptr_array_new ();
+ GHashTableIter iter;
+ gpointer k;
+ guint i;
+
+ /* We don't actually store any parameters, but for the purposes
+ * of this method we pretend that every parameter provided is
+ * valid and requires reconnection. */
+
+ g_hash_table_iter_init (&iter, parameters);
+
+ while (g_hash_table_iter_next (&iter, &k, NULL))
+ g_ptr_array_add (reconnect_required, k);
+
+ for (i = 0; unset_parameters != NULL && unset_parameters[i] != NULL; i++)
+ g_ptr_array_add (reconnect_required, (gchar *) unset_parameters[i]);
+
+ g_ptr_array_add (reconnect_required, NULL);
+
+ tp_svc_account_return_from_update_parameters (context,
+ (const gchar **) reconnect_required->pdata);
+ g_ptr_array_unref (reconnect_required);
+}
+
+static void
+account_iface_init (gpointer klass,
+ gpointer unused G_GNUC_UNUSED)
+{
+#define IMPLEMENT(x) tp_svc_account_implement_##x (\
+ klass, tp_tests_simple_account_##x)
+ IMPLEMENT (update_parameters);
+#undef IMPLEMENT
+}
+
+
+static void
+tp_tests_simple_account_init (TpTestsSimpleAccount *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TESTS_TYPE_SIMPLE_ACCOUNT,
+ TpTestsSimpleAccountPrivate);
+
+ self->priv->presence = TP_CONNECTION_PRESENCE_TYPE_AWAY;
+ self->priv->presence_status = g_strdup ("currently-away");
+ self->priv->presence_msg = g_strdup ("this is my CurrentPresence");
+ self->priv->connection_path = g_strdup ("/");
+ self->priv->enabled = TRUE;
+}
+
+/* you may have noticed this is not entirely realistic */
+static const gchar * const uri_schemes[] = { "about", "telnet", NULL };
+
+static void
+tp_tests_simple_account_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *spec)
+{
+ TpTestsSimpleAccount *self = TP_TESTS_SIMPLE_ACCOUNT (object);
+ GValue identifier = { 0, };
+
+ g_value_init (&identifier, G_TYPE_STRING);
+ g_value_set_string (&identifier, "unique-identifier");
+
+ switch (property_id) {
+ case PROP_INTERFACES:
+ g_value_set_boxed (value, ACCOUNT_INTERFACES);
+ break;
+ case PROP_DISPLAY_NAME:
+ g_value_set_string (value, "Fake Account");
+ break;
+ case PROP_ICON:
+ g_value_set_string (value, "");
+ break;
+ case PROP_VALID:
+ g_value_set_boolean (value, TRUE);
+ break;
+ case PROP_ENABLED:
+ g_value_set_boolean (value, self->priv->enabled);
+ break;
+ case PROP_NICKNAME:
+ g_value_set_string (value, "badger");
+ break;
+ case PROP_PARAMETERS:
+ g_value_take_boxed (value, g_hash_table_new (NULL, NULL));
+ break;
+ case PROP_AUTOMATIC_PRESENCE:
+ g_value_take_boxed (value, tp_value_array_build (3,
+ G_TYPE_UINT, TP_CONNECTION_PRESENCE_TYPE_AVAILABLE,
+ G_TYPE_STRING, "automatically-available",
+ G_TYPE_STRING, "this is my AutomaticPresence",
+ G_TYPE_INVALID));
+ break;
+ case PROP_CONNECT_AUTO:
+ g_value_set_boolean (value, FALSE);
+ break;
+ case PROP_CONNECTION:
+ g_value_set_boxed (value, self->priv->connection_path);
+ break;
+ case PROP_CONNECTION_STATUS:
+ g_value_set_uint (value, TP_CONNECTION_STATUS_CONNECTED);
+ break;
+ case PROP_CONNECTION_STATUS_REASON:
+ g_value_set_uint (value, TP_CONNECTION_STATUS_REASON_REQUESTED);
+ break;
+ case PROP_CURRENT_PRESENCE:
+ g_value_take_boxed (value, tp_value_array_build (3,
+ G_TYPE_UINT, self->priv->presence,
+ G_TYPE_STRING, self->priv->presence_status,
+ G_TYPE_STRING, self->priv->presence_msg,
+ G_TYPE_INVALID));
+ break;
+ case PROP_REQUESTED_PRESENCE:
+ g_value_take_boxed (value, tp_value_array_build (3,
+ G_TYPE_UINT, TP_CONNECTION_PRESENCE_TYPE_BUSY,
+ G_TYPE_STRING, "requesting",
+ G_TYPE_STRING, "this is my RequestedPresence",
+ G_TYPE_INVALID));
+ break;
+ case PROP_NORMALIZED_NAME:
+ g_value_set_string (value, "bob mcbadgers example com");
+ break;
+ case PROP_HAS_BEEN_ONLINE:
+ g_value_set_boolean (value, TRUE);
+ break;
+ case PROP_STORAGE_PROVIDER:
+ g_value_set_string (value, "org.freedesktop.Telepathy.glib.test");
+ break;
+ case PROP_STORAGE_IDENTIFIER:
+ g_value_set_boxed (value, &identifier);
+ break;
+ case PROP_STORAGE_SPECIFIC_INFORMATION:
+ g_value_take_boxed (value, tp_asv_new (
+ "one", G_TYPE_INT, 1,
+ "two", G_TYPE_UINT, 2,
+ "marco", G_TYPE_STRING, "polo",
+ NULL));
+ break;
+ case PROP_STORAGE_RESTRICTIONS:
+ g_value_set_uint (value,
+ TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_ENABLED |
+ TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_PARAMETERS);
+ break;
+ case PROP_URI_SCHEMES:
+ g_value_set_boxed (value, uri_schemes);
+ break;
+ case PROP_AVATAR:
+ {
+ GArray *arr = g_array_new (FALSE, FALSE, sizeof (char));
+
+ /* includes NUL for simplicity */
+ g_array_append_vals (arr, ":-)", 4);
+
+ g_value_take_boxed (value,
+ tp_value_array_build (2,
+ TP_TYPE_UCHAR_ARRAY, arr,
+ G_TYPE_STRING, "text/plain",
+ G_TYPE_INVALID));
+ g_array_unref (arr);
+ }
+ break;
+ case PROP_SUPERSEDES:
+ {
+ GPtrArray *arr = g_ptr_array_new ();
+
+ g_ptr_array_add (arr,
+ g_strdup (TP_ACCOUNT_OBJECT_PATH_BASE "super/seded/whatever"));
+ g_value_take_boxed (value, arr);
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec);
+ break;
+ }
+
+ g_value_unset (&identifier);
+}
+
+static void
+tp_tests_simple_account_finalize (GObject *object)
+{
+ TpTestsSimpleAccount *self = TP_TESTS_SIMPLE_ACCOUNT (object);
+
+ g_free (self->priv->presence_status);
+ g_free (self->priv->presence_msg);
+
+ G_OBJECT_CLASS (tp_tests_simple_account_parent_class)->finalize (object);
+}
+
+/**
+ * This class currently only provides the minimum for
+ * tp_account_prepare to succeed. This turns out to be only a working
+ * Properties.GetAll().
+ */
+static void
+tp_tests_simple_account_class_init (TpTestsSimpleAccountClass *klass)
+{
+ GObjectClass *object_class = (GObjectClass *) klass;
+ GParamSpec *param_spec;
+
+ static TpDBusPropertiesMixinPropImpl a_props[] = {
+ { "Interfaces", "interfaces", NULL },
+ { "DisplayName", "display-name", NULL },
+ { "Icon", "icon", NULL },
+ { "Valid", "valid", NULL },
+ { "Enabled", "enabled", NULL },
+ { "Nickname", "nickname", NULL },
+ { "Parameters", "parameters", NULL },
+ { "AutomaticPresence", "automatic-presence", NULL },
+ { "ConnectAutomatically", "connect-automatically", NULL },
+ { "Connection", "connection", NULL },
+ { "ConnectionStatus", "connection-status", NULL },
+ { "ConnectionStatusReason", "connection-status-reason", NULL },
+ { "CurrentPresence", "current-presence", NULL },
+ { "RequestedPresence", "requested-presence", NULL },
+ { "NormalizedName", "normalized-name", NULL },
+ { "HasBeenOnline", "has-been-online", NULL },
+ { "Supersedes", "supersedes", NULL },
+ { NULL }
+ };
+
+ static TpDBusPropertiesMixinPropImpl ais_props[] = {
+ { "StorageProvider", "storage-provider", NULL },
+ { "StorageIdentifier", "storage-identifier", NULL },
+ { "StorageSpecificInformation", "storage-specific-information", NULL },
+ { "StorageRestrictions", "storage-restrictions", NULL },
+ { NULL },
+ };
+
+ static TpDBusPropertiesMixinPropImpl aia_props[] = {
+ { "URISchemes", "uri-schemes", NULL },
+ { NULL },
+ };
+
+ static TpDBusPropertiesMixinPropImpl avatar_props[] = {
+ { "Avatar", "avatar", NULL },
+ { NULL },
+ };
+
+ static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
+ { TP_IFACE_ACCOUNT,
+ tp_dbus_properties_mixin_getter_gobject_properties,
+ NULL,
+ a_props
+ },
+ {
+ TP_IFACE_ACCOUNT_INTERFACE_STORAGE,
+ tp_dbus_properties_mixin_getter_gobject_properties,
+ NULL,
+ ais_props
+ },
+ {
+ TP_IFACE_ACCOUNT_INTERFACE_ADDRESSING,
+ tp_dbus_properties_mixin_getter_gobject_properties,
+ NULL,
+ aia_props
+ },
+ { TP_IFACE_ACCOUNT_INTERFACE_AVATAR,
+ tp_dbus_properties_mixin_getter_gobject_properties,
+ NULL,
+ avatar_props
+ },
+ { NULL },
+ };
+
+ g_type_class_add_private (klass, sizeof (TpTestsSimpleAccountPrivate));
+ object_class->get_property = tp_tests_simple_account_get_property;
+ object_class->finalize = tp_tests_simple_account_finalize;
+
+ param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces",
+ "In this case we only implement Account, so none.",
+ G_TYPE_STRV,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_INTERFACES, param_spec);
+
+ param_spec = g_param_spec_string ("display-name", "display name",
+ "DisplayName property",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_DISPLAY_NAME, param_spec);
+
+ param_spec = g_param_spec_string ("icon", "icon",
+ "Icon property",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_ICON, param_spec);
+
+ param_spec = g_param_spec_boolean ("valid", "valid",
+ "Valid property",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_VALID, param_spec);
+
+ param_spec = g_param_spec_boolean ("enabled", "enabled",
+ "Enabled property",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_ENABLED, param_spec);
+
+ param_spec = g_param_spec_string ("nickname", "nickname",
+ "Nickname property",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_NICKNAME, param_spec);
+
+ param_spec = g_param_spec_boxed ("parameters", "parameters",
+ "Parameters property",
+ TP_HASH_TYPE_STRING_VARIANT_MAP,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_PARAMETERS, param_spec);
+
+ param_spec = g_param_spec_boxed ("automatic-presence", "automatic presence",
+ "AutomaticPresence property",
+ TP_STRUCT_TYPE_SIMPLE_PRESENCE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_AUTOMATIC_PRESENCE,
+ param_spec);
+
+ param_spec = g_param_spec_boolean ("connect-automatically",
+ "connect automatically", "ConnectAutomatically property",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CONNECT_AUTO, param_spec);
+
+ param_spec = g_param_spec_boxed ("connection", "connection",
+ "Connection property",
+ DBUS_TYPE_G_OBJECT_PATH,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
+
+ param_spec = g_param_spec_uint ("connection-status", "connection status",
+ "ConnectionStatus property",
+ 0, NUM_TP_CONNECTION_STATUSES, TP_CONNECTION_STATUS_DISCONNECTED,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CONNECTION_STATUS,
+ param_spec);
+
+ param_spec = g_param_spec_uint ("connection-status-reason",
+ "connection status reason", "ConnectionStatusReason property",
+ 0, NUM_TP_CONNECTION_STATUS_REASONS,
+ TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CONNECTION_STATUS_REASON,
+ param_spec);
+
+ param_spec = g_param_spec_boxed ("current-presence", "current presence",
+ "CurrentPresence property",
+ TP_STRUCT_TYPE_SIMPLE_PRESENCE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CURRENT_PRESENCE,
+ param_spec);
+
+ param_spec = g_param_spec_boxed ("requested-presence", "requested presence",
+ "RequestedPresence property",
+ TP_STRUCT_TYPE_SIMPLE_PRESENCE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_REQUESTED_PRESENCE,
+ param_spec);
+
+ param_spec = g_param_spec_string ("normalized-name", "normalized name",
+ "NormalizedName property",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_NORMALIZED_NAME,
+ param_spec);
+
+ param_spec = g_param_spec_boolean ("has-been-online", "has been online",
+ "HasBeenOnline property",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_HAS_BEEN_ONLINE,
+ param_spec);
+
+ param_spec = g_param_spec_string ("storage-provider", "storage provider",
+ "StorageProvider property",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_STORAGE_PROVIDER,
+ param_spec);
+
+ param_spec = g_param_spec_boxed ("storage-identifier", "storage identifier",
+ "StorageIdentifier property",
+ G_TYPE_VALUE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_STORAGE_IDENTIFIER,
+ param_spec);
+
+ param_spec = g_param_spec_boxed ("storage-specific-information",
+ "storage specific information", "StorageSpecificInformation property",
+ TP_HASH_TYPE_STRING_VARIANT_MAP,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class,
+ PROP_STORAGE_SPECIFIC_INFORMATION, param_spec);
+
+ param_spec = g_param_spec_uint ("storage-restrictions",
+ "storage restrictions", "StorageRestrictions property",
+ 0, G_MAXUINT, 0,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_STORAGE_RESTRICTIONS,
+ param_spec);
+
+ param_spec = g_param_spec_boxed ("uri-schemes", "URI schemes",
+ "Some URI schemes",
+ G_TYPE_STRV,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_URI_SCHEMES, param_spec);
+
+ param_spec = g_param_spec_boxed ("avatar",
+ "Avatar", "Avatar",
+ TP_STRUCT_TYPE_AVATAR,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class,
+ PROP_AVATAR, param_spec);
+
+ param_spec = g_param_spec_boxed ("supersedes",
+ "Supersedes", "List of superseded accounts",
+ TP_ARRAY_TYPE_OBJECT_PATH_LIST,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class,
+ PROP_SUPERSEDES, param_spec);
+
+ klass->dbus_props_class.interfaces = prop_interfaces;
+ tp_dbus_properties_mixin_class_init (object_class,
+ G_STRUCT_OFFSET (TpTestsSimpleAccountClass, dbus_props_class));
+}
+
+void
+tp_tests_simple_account_set_presence (TpTestsSimpleAccount *self,
+ TpConnectionPresenceType presence,
+ const gchar *status,
+ const gchar *message)
+{
+ GHashTable *props;
+ GValueArray *v;
+
+ g_free (self->priv->presence_status);
+ g_free (self->priv->presence_msg);
+
+ self->priv->presence = presence;
+ self->priv->presence_status = g_strdup (status);
+ self->priv->presence_msg = g_strdup (message);
+
+ g_object_get (self, "current-presence", &v, NULL);
+
+ props = tp_asv_new (
+ "CurrentPresence", TP_STRUCT_TYPE_SIMPLE_PRESENCE, v,
+ NULL);
+
+ tp_svc_account_emit_account_property_changed (self, props);
+
+ g_boxed_free (TP_STRUCT_TYPE_SIMPLE_PRESENCE, v);
+}
+
+void
+tp_tests_simple_account_set_connection (TpTestsSimpleAccount *self,
+ const gchar *object_path)
+{
+ GHashTable *change;
+
+ if (object_path == NULL)
+ object_path = "/";
+
+ g_free (self->priv->connection_path);
+ self->priv->connection_path = g_strdup (object_path);
+
+ change = tp_asv_new (NULL, NULL);
+ tp_asv_set_string (change, "Connection", object_path);
+ tp_svc_account_emit_account_property_changed (self, change);
+ g_hash_table_unref (change);
+}
+
+void
+tp_tests_simple_account_removed (TpTestsSimpleAccount *self)
+{
+ tp_svc_account_emit_removed (self);
+}
+
+void
+tp_tests_simple_account_set_enabled (TpTestsSimpleAccount *self,
+ gboolean enabled)
+{
+ GHashTable *change;
+
+ self->priv->enabled = enabled;
+
+ change = tp_asv_new (NULL, NULL);
+ tp_asv_set_boolean (change, "Enabled", enabled);
+ tp_svc_account_emit_account_property_changed (self, change);
+ g_hash_table_unref (change);
+}
diff --git a/tests/lib/telepathy/contactlist/simple-account.h b/tests/lib/telepathy/contactlist/simple-account.h
new file mode 100644
index 0000000..2ce3efd
--- /dev/null
+++ b/tests/lib/telepathy/contactlist/simple-account.h
@@ -0,0 +1,69 @@
+/*
+ * simple-account.h - header for a simple account service.
+ *
+ * Copyright (C) 2010-2012 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved.
+ */
+
+#ifndef __TP_TESTS_SIMPLE_ACCOUNT_H__
+#define __TP_TESTS_SIMPLE_ACCOUNT_H__
+
+#include <glib-object.h>
+
+#include <telepathy-glib/connection.h>
+#include <telepathy-glib/dbus-properties-mixin.h>
+
+G_BEGIN_DECLS
+
+typedef struct _TpTestsSimpleAccount TpTestsSimpleAccount;
+typedef struct _TpTestsSimpleAccountClass TpTestsSimpleAccountClass;
+typedef struct _TpTestsSimpleAccountPrivate TpTestsSimpleAccountPrivate;
+
+struct _TpTestsSimpleAccountClass {
+ GObjectClass parent_class;
+ TpDBusPropertiesMixinClass dbus_props_class;
+};
+
+struct _TpTestsSimpleAccount {
+ GObject parent;
+
+ TpTestsSimpleAccountPrivate *priv;
+};
+
+GType tp_tests_simple_account_get_type (void);
+
+/* TYPE MACROS */
+#define TP_TESTS_TYPE_SIMPLE_ACCOUNT \
+ (tp_tests_simple_account_get_type ())
+#define TP_TESTS_SIMPLE_ACCOUNT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_SIMPLE_ACCOUNT, \
+ TpTestsSimpleAccount))
+#define TP_TESTS_SIMPLE_ACCOUNT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_SIMPLE_ACCOUNT, \
+ TpTestsSimpleAccountClass))
+#define TP_TESTS_SIMPLE_IS_ACCOUNT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_SIMPLE_ACCOUNT))
+#define TP_TESTS_SIMPLE_IS_ACCOUNT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_SIMPLE_ACCOUNT))
+#define TP_TESTS_SIMPLE_ACCOUNT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_SIMPLE_ACCOUNT, \
+ TpTestsSimpleAccountClass))
+
+void tp_tests_simple_account_set_presence (TpTestsSimpleAccount *self,
+ TpConnectionPresenceType presence,
+ const gchar *status,
+ const gchar *message);
+
+void tp_tests_simple_account_set_connection (TpTestsSimpleAccount *self,
+ const gchar *object_path);
+
+void tp_tests_simple_account_removed (TpTestsSimpleAccount *self);
+void tp_tests_simple_account_set_enabled (TpTestsSimpleAccount *self,
+ gboolean enabled);
+
+G_END_DECLS
+
+#endif /* #ifndef __TP_TESTS_SIMPLE_ACCOUNT_H__ */
diff --git a/tests/lib/telepathy/contactlist/simple-conn.c b/tests/lib/telepathy/contactlist/simple-conn.c
new file mode 100644
index 0000000..8a481af
--- /dev/null
+++ b/tests/lib/telepathy/contactlist/simple-conn.c
@@ -0,0 +1,452 @@
+/*
+ * simple-conn.c - a simple connection
+ *
+ * Copyright (C) 2007-2010 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright (C) 2007-2008 Nokia Corporation
+ *
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved.
+ */
+
+#include "config.h"
+
+#include "simple-conn.h"
+
+#include <string.h>
+
+#include <dbus/dbus-glib.h>
+
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/errors.h>
+#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/handle-repo-dynamic.h>
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/util.h>
+
+#include "textchan-null.h"
+#include "util.h"
+
+static void conn_iface_init (TpSvcConnectionClass *);
+
+G_DEFINE_TYPE_WITH_CODE (TpTestsSimpleConnection, tp_tests_simple_connection,
+ TP_TYPE_BASE_CONNECTION,
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION, conn_iface_init))
+
+/* type definition stuff */
+
+enum
+{
+ PROP_ACCOUNT = 1,
+ PROP_BREAK_PROPS = 2,
+ PROP_DBUS_STATUS = 3,
+ N_PROPS
+};
+
+enum
+{
+ SIGNAL_GOT_SELF_HANDLE,
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS] = {0};
+
+struct _TpTestsSimpleConnectionPrivate
+{
+ gchar *account;
+ guint connect_source;
+ guint disconnect_source;
+ gboolean break_fastpath_props;
+
+ /* TpHandle => reffed TpTestsTextChannelNull */
+ GHashTable *channels;
+
+ GError *get_self_handle_error /* initially NULL */ ;
+};
+
+static void
+tp_tests_simple_connection_init (TpTestsSimpleConnection *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ TP_TESTS_TYPE_SIMPLE_CONNECTION, TpTestsSimpleConnectionPrivate);
+
+ self->priv->channels = g_hash_table_new_full (NULL, NULL, NULL,
+ (GDestroyNotify) g_object_unref);
+}
+
+static void
+get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *spec)
+{
+ TpTestsSimpleConnection *self = TP_TESTS_SIMPLE_CONNECTION (object);
+
+ switch (property_id) {
+ case PROP_ACCOUNT:
+ g_value_set_string (value, self->priv->account);
+ break;
+ case PROP_BREAK_PROPS:
+ g_value_set_boolean (value, self->priv->break_fastpath_props);
+ break;
+ case PROP_DBUS_STATUS:
+ if (self->priv->break_fastpath_props)
+ {
+ g_debug ("returning broken value for Connection.Status");
+ g_value_set_uint (value, 0xdeadbeefU);
+ }
+ else
+ {
+ guint32 status = TP_BASE_CONNECTION (self)->status;
+
+ if (status == TP_INTERNAL_CONNECTION_STATUS_NEW)
+ g_value_set_uint (value, TP_CONNECTION_STATUS_DISCONNECTED);
+ else
+ g_value_set_uint (value, status);
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec);
+ }
+}
+
+static void
+set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *spec)
+{
+ TpTestsSimpleConnection *self = TP_TESTS_SIMPLE_CONNECTION (object);
+
+ switch (property_id) {
+ case PROP_ACCOUNT:
+ g_free (self->priv->account);
+ self->priv->account = g_utf8_strdown (g_value_get_string (value), -1);
+ break;
+ case PROP_BREAK_PROPS:
+ self->priv->break_fastpath_props = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec);
+ }
+}
+
+static void
+dispose (GObject *object)
+{
+ TpTestsSimpleConnection *self = TP_TESTS_SIMPLE_CONNECTION (object);
+
+ g_hash_table_unref (self->priv->channels);
+
+ G_OBJECT_CLASS (tp_tests_simple_connection_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+ TpTestsSimpleConnection *self = TP_TESTS_SIMPLE_CONNECTION (object);
+
+ if (self->priv->connect_source != 0)
+ {
+ g_source_remove (self->priv->connect_source);
+ }
+
+ if (self->priv->disconnect_source != 0)
+ {
+ g_source_remove (self->priv->disconnect_source);
+ }
+
+ g_clear_error (&self->priv->get_self_handle_error);
+ g_free (self->priv->account);
+
+ G_OBJECT_CLASS (tp_tests_simple_connection_parent_class)->finalize (object);
+}
+
+static gchar *
+get_unique_connection_name (TpBaseConnection *conn)
+{
+ TpTestsSimpleConnection *self = TP_TESTS_SIMPLE_CONNECTION (conn);
+
+ return g_strdup (self->priv->account);
+}
+
+static gchar *
+tp_tests_simple_normalize_contact (TpHandleRepoIface *repo,
+ const gchar *id,
+ gpointer context,
+ GError **error)
+{
+ if (id[0] == '\0')
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_HANDLE,
+ "ID must not be empty");
+ return NULL;
+ }
+
+ if (strchr (id, ' ') != NULL)
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_HANDLE,
+ "ID must not contain spaces");
+ return NULL;
+ }
+
+ return g_utf8_strdown (id, -1);
+}
+
+static void
+create_handle_repos (TpBaseConnection *conn,
+ TpHandleRepoIface *repos[NUM_TP_HANDLE_TYPES])
+{
+ repos[TP_HANDLE_TYPE_CONTACT] = tp_dynamic_handle_repo_new
+ (TP_HANDLE_TYPE_CONTACT, tp_tests_simple_normalize_contact, NULL);
+ repos[TP_HANDLE_TYPE_ROOM] = tp_dynamic_handle_repo_new
+ (TP_HANDLE_TYPE_ROOM, NULL, NULL);
+}
+
+static GPtrArray *
+create_channel_factories (TpBaseConnection *conn)
+{
+ return g_ptr_array_sized_new (0);
+}
+
+void
+tp_tests_simple_connection_inject_disconnect (TpTestsSimpleConnection *self)
+{
+ tp_base_connection_change_status ((TpBaseConnection *) self,
+ TP_CONNECTION_STATUS_DISCONNECTED,
+ TP_CONNECTION_STATUS_REASON_REQUESTED);
+}
+
+static gboolean
+pretend_connected (gpointer data)
+{
+ TpTestsSimpleConnection *self = TP_TESTS_SIMPLE_CONNECTION (data);
+ TpBaseConnection *conn = (TpBaseConnection *) self;
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn,
+ TP_HANDLE_TYPE_CONTACT);
+
+ conn->self_handle = tp_handle_ensure (contact_repo, self->priv->account,
+ NULL, NULL);
+
+ if (conn->status == TP_CONNECTION_STATUS_CONNECTING)
+ {
+ tp_base_connection_change_status (conn, TP_CONNECTION_STATUS_CONNECTED,
+ TP_CONNECTION_STATUS_REASON_REQUESTED);
+ }
+
+ self->priv->connect_source = 0;
+ return FALSE;
+}
+
+static gboolean
+start_connecting (TpBaseConnection *conn,
+ GError **error)
+{
+ TpTestsSimpleConnection *self = TP_TESTS_SIMPLE_CONNECTION (conn);
+
+ tp_base_connection_change_status (conn, TP_CONNECTION_STATUS_CONNECTING,
+ TP_CONNECTION_STATUS_REASON_REQUESTED);
+
+ /* In a real connection manager we'd ask the underlying implementation to
+ * start connecting, then go to state CONNECTED when finished. Here there
+ * isn't actually a connection, so we'll fake a connection process that
+ * takes time. */
+ self->priv->connect_source = g_timeout_add (0, pretend_connected, self);
+
+ return TRUE;
+}
+
+static gboolean
+pretend_disconnected (gpointer data)
+{
+ TpTestsSimpleConnection *self = TP_TESTS_SIMPLE_CONNECTION (data);
+
+ /* We are disconnected, all our channels are invalidated */
+ g_hash_table_remove_all (self->priv->channels);
+
+ tp_base_connection_finish_shutdown (TP_BASE_CONNECTION (data));
+ self->priv->disconnect_source = 0;
+ return FALSE;
+}
+
+static void
+shut_down (TpBaseConnection *conn)
+{
+ TpTestsSimpleConnection *self = TP_TESTS_SIMPLE_CONNECTION (conn);
+
+ /* In a real connection manager we'd ask the underlying implementation to
+ * start shutting down, then call this function when finished. Here there
+ * isn't actually a connection, so we'll fake a disconnection process that
+ * takes time. */
+ self->priv->disconnect_source = g_timeout_add (0, pretend_disconnected,
+ conn);
+}
+
+static void
+tp_tests_simple_connection_class_init (TpTestsSimpleConnectionClass *klass)
+{
+ TpBaseConnectionClass *base_class =
+ (TpBaseConnectionClass *) klass;
+ GObjectClass *object_class = (GObjectClass *) klass;
+ GParamSpec *param_spec;
+ static const gchar *interfaces_always_present[] = {
+ TP_IFACE_CONNECTION_INTERFACE_REQUESTS, NULL };
+
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+ object_class->dispose = dispose;
+ object_class->finalize = finalize;
+ g_type_class_add_private (klass, sizeof (TpTestsSimpleConnectionPrivate));
+
+ base_class->create_handle_repos = create_handle_repos;
+ base_class->get_unique_connection_name = get_unique_connection_name;
+ base_class->create_channel_factories = create_channel_factories;
+ base_class->start_connecting = start_connecting;
+ base_class->shut_down = shut_down;
+
+ base_class->interfaces_always_present = interfaces_always_present;
+
+ param_spec = g_param_spec_string ("account", "Account name",
+ "The username of this user", NULL,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_ACCOUNT, param_spec);
+
+ param_spec = g_param_spec_boolean ("break-0192-properties",
+ "Break 0.19.2 properties",
+ "Break Connection D-Bus properties introduced in spec 0.19.2", FALSE,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_BREAK_PROPS, param_spec);
+
+ param_spec = g_param_spec_uint ("dbus-status",
+ "Connection.Status",
+ "The connection status as visible on D-Bus (overridden so can break it)",
+ TP_CONNECTION_STATUS_CONNECTED, G_MAXUINT,
+ TP_CONNECTION_STATUS_DISCONNECTED,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_DBUS_STATUS, param_spec);
+
+ signals[SIGNAL_GOT_SELF_HANDLE] = g_signal_new ("got-self-handle",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+}
+
+void
+tp_tests_simple_connection_set_identifier (TpTestsSimpleConnection *self,
+ const gchar *identifier)
+{
+ TpBaseConnection *conn = (TpBaseConnection *) self;
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn,
+ TP_HANDLE_TYPE_CONTACT);
+ TpHandle handle = tp_handle_ensure (contact_repo, identifier, NULL, NULL);
+
+ /* if this fails then the identifier was bad - caller error */
+ g_return_if_fail (handle != 0);
+
+ tp_base_connection_set_self_handle (conn, handle);
+ tp_handle_unref (contact_repo, handle);
+}
+
+TpTestsSimpleConnection *
+tp_tests_simple_connection_new (const gchar *account,
+ const gchar *protocol)
+{
+ return TP_TESTS_SIMPLE_CONNECTION (g_object_new (
+ TP_TESTS_TYPE_SIMPLE_CONNECTION,
+ "account", account,
+ "protocol", protocol,
+ NULL));
+}
+
+gchar *
+tp_tests_simple_connection_ensure_text_chan (TpTestsSimpleConnection *self,
+ const gchar *target_id,
+ GHashTable **props)
+{
+ TpTestsTextChannelNull *chan;
+ gchar *chan_path;
+ TpHandleRepoIface *contact_repo;
+ TpHandle handle;
+ static guint count = 0;
+ TpBaseConnection *base_conn = (TpBaseConnection *) self;
+
+ /* Get contact handle */
+ contact_repo = tp_base_connection_get_handles (base_conn,
+ TP_HANDLE_TYPE_CONTACT);
+ g_assert (contact_repo != NULL);
+
+ handle = tp_handle_ensure (contact_repo, target_id, NULL, NULL);
+
+ chan = g_hash_table_lookup (self->priv->channels, GUINT_TO_POINTER (handle));
+ if (chan != NULL)
+ {
+ /* Channel already exist, reuse it */
+ g_object_get (chan, "object-path", &chan_path, NULL);
+ }
+ else
+ {
+ chan_path = g_strdup_printf ("%s/Channel%u", base_conn->object_path,
+ count++);
+
+ chan = TP_TESTS_TEXT_CHANNEL_NULL (
+ tp_tests_object_new_static_class (
+ TP_TESTS_TYPE_TEXT_CHANNEL_NULL,
+ "connection", self,
+ "object-path", chan_path,
+ "handle", handle,
+ NULL));
+
+ g_hash_table_insert (self->priv->channels, GUINT_TO_POINTER (handle),
+ chan);
+ }
+
+ tp_handle_unref (contact_repo, handle);
+
+ if (props != NULL)
+ *props = tp_tests_text_channel_get_props (chan);
+
+ return chan_path;
+}
+
+void
+tp_tests_simple_connection_set_get_self_handle_error (
+ TpTestsSimpleConnection *self,
+ GQuark domain,
+ gint code,
+ const gchar *message)
+{
+ self->priv->get_self_handle_error = g_error_new_literal (domain, code,
+ message);
+}
+
+static void
+get_self_handle (TpSvcConnection *iface,
+ DBusGMethodInvocation *context)
+{
+ TpTestsSimpleConnection *self = TP_TESTS_SIMPLE_CONNECTION (iface);
+ TpBaseConnection *base = TP_BASE_CONNECTION (iface);
+
+ g_assert (TP_IS_BASE_CONNECTION (base));
+
+ TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+ if (self->priv->get_self_handle_error != NULL)
+ {
+ dbus_g_method_return_error (context, self->priv->get_self_handle_error);
+ return;
+ }
+
+ tp_svc_connection_return_from_get_self_handle (context, base->self_handle);
+ g_signal_emit (self, signals[SIGNAL_GOT_SELF_HANDLE], 0);
+}
+
+static void
+conn_iface_init (TpSvcConnectionClass *iface)
+{
+#define IMPLEMENT(prefix,x) \
+ tp_svc_connection_implement_##x (iface, prefix##x)
+ IMPLEMENT(,get_self_handle);
+#undef IMPLEMENT
+}
diff --git a/tests/lib/telepathy/contactlist/simple-conn.h b/tests/lib/telepathy/contactlist/simple-conn.h
new file mode 100644
index 0000000..6322f4b
--- /dev/null
+++ b/tests/lib/telepathy/contactlist/simple-conn.h
@@ -0,0 +1,77 @@
+/*
+ * simple-conn.h - header for a simple connection
+ *
+ * Copyright (C) 2007-2008 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright (C) 2007-2008 Nokia Corporation
+ *
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved.
+ */
+
+#ifndef __TP_TESTS_SIMPLE_CONN_H__
+#define __TP_TESTS_SIMPLE_CONN_H__
+
+#include <glib-object.h>
+#include <telepathy-glib/base-connection.h>
+
+G_BEGIN_DECLS
+
+typedef struct _TpTestsSimpleConnection TpTestsSimpleConnection;
+typedef struct _TpTestsSimpleConnectionClass TpTestsSimpleConnectionClass;
+typedef struct _TpTestsSimpleConnectionPrivate TpTestsSimpleConnectionPrivate;
+
+struct _TpTestsSimpleConnectionClass {
+ TpBaseConnectionClass parent_class;
+};
+
+struct _TpTestsSimpleConnection {
+ TpBaseConnection parent;
+
+ TpTestsSimpleConnectionPrivate *priv;
+};
+
+GType tp_tests_simple_connection_get_type (void);
+
+/* TYPE MACROS */
+#define TP_TESTS_TYPE_SIMPLE_CONNECTION \
+ (tp_tests_simple_connection_get_type ())
+#define TP_TESTS_SIMPLE_CONNECTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_SIMPLE_CONNECTION, \
+ TpTestsSimpleConnection))
+#define TP_TESTS_SIMPLE_CONNECTION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_SIMPLE_CONNECTION, \
+ TpTestsSimpleConnectionClass))
+#define TP_TESTS_SIMPLE_IS_CONNECTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_SIMPLE_CONNECTION))
+#define TP_TESTS_SIMPLE_IS_CONNECTION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_SIMPLE_CONNECTION))
+#define TP_TESTS_SIMPLE_CONNECTION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_SIMPLE_CONNECTION, \
+ TpTestsSimpleConnectionClass))
+
+TpTestsSimpleConnection * tp_tests_simple_connection_new (const gchar *account,
+ const gchar *protocol);
+
+/* Cause "network events", for debugging/testing */
+
+void tp_tests_simple_connection_inject_disconnect (
+ TpTestsSimpleConnection *self);
+
+void tp_tests_simple_connection_set_identifier (TpTestsSimpleConnection *self,
+ const gchar *identifier);
+
+gchar * tp_tests_simple_connection_ensure_text_chan (
+ TpTestsSimpleConnection *self,
+ const gchar *target_id,
+ GHashTable **props);
+
+void tp_tests_simple_connection_set_get_self_handle_error (
+ TpTestsSimpleConnection *self,
+ GQuark domain,
+ gint code,
+ const gchar *message);
+
+G_END_DECLS
+
+#endif /* #ifndef __TP_TESTS_SIMPLE_CONN_H__ */
diff --git a/tests/lib/telepathy/contactlist/textchan-null.c b/tests/lib/telepathy/contactlist/textchan-null.c
new file mode 100644
index 0000000..5765944
--- /dev/null
+++ b/tests/lib/telepathy/contactlist/textchan-null.c
@@ -0,0 +1,571 @@
+/*
+ * /dev/null as a text channel
+ *
+ * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved.
+ */
+
+#include "config.h"
+
+#include "textchan-null.h"
+
+#include <telepathy-glib/base-connection.h>
+#include <telepathy-glib/channel-iface.h>
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/dbus-properties-mixin.h>
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/svc-channel.h>
+#include <telepathy-glib/svc-generic.h>
+
+static void text_iface_init (gpointer iface, gpointer data);
+static void channel_iface_init (gpointer iface, gpointer data);
+
+G_DEFINE_TYPE_WITH_CODE (TpTestsTextChannelNull,
+ tp_tests_text_channel_null,
+ G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_TEXT, text_iface_init);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL))
+
+G_DEFINE_TYPE_WITH_CODE (TpTestsPropsTextChannel,
+ tp_tests_props_text_channel,
+ TP_TESTS_TYPE_TEXT_CHANNEL_NULL,
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
+ tp_dbus_properties_mixin_iface_init))
+
+G_DEFINE_TYPE_WITH_CODE (TpTestsPropsGroupTextChannel,
+ tp_tests_props_group_text_channel,
+ TP_TESTS_TYPE_PROPS_TEXT_CHANNEL,
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP,
+ tp_group_mixin_iface_init))
+
+static const char *tp_tests_text_channel_null_interfaces[] = { NULL };
+
+/* type definition stuff */
+
+enum
+{
+ PROP_OBJECT_PATH = 1,
+ PROP_CHANNEL_TYPE,
+ PROP_HANDLE_TYPE,
+ PROP_HANDLE,
+ PROP_TARGET_ID,
+ PROP_CONNECTION,
+ PROP_INTERFACES,
+ PROP_REQUESTED,
+ PROP_INITIATOR_HANDLE,
+ PROP_INITIATOR_ID,
+ N_PROPS
+};
+
+struct _TpTestsTextChannelNullPrivate
+{
+ TpBaseConnection *conn;
+ gchar *object_path;
+ TpHandle handle;
+
+ unsigned closed:1;
+ unsigned disposed:1;
+};
+
+static void
+tp_tests_text_channel_null_init (TpTestsTextChannelNull *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ TP_TESTS_TYPE_TEXT_CHANNEL_NULL, TpTestsTextChannelNullPrivate);
+}
+
+static void
+tp_tests_props_text_channel_init (TpTestsPropsTextChannel *self)
+{
+ self->dbus_property_interfaces_retrieved = g_hash_table_new (NULL, NULL);
+}
+
+static GObject *
+constructor (GType type,
+ guint n_props,
+ GObjectConstructParam *props)
+{
+ GObject *object =
+ G_OBJECT_CLASS (tp_tests_text_channel_null_parent_class)->constructor (type,
+ n_props, props);
+ TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (object);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles
+ (self->priv->conn, TP_HANDLE_TYPE_CONTACT);
+
+ tp_handle_ref (contact_repo, self->priv->handle);
+
+ tp_dbus_daemon_register_object (
+ tp_base_connection_get_dbus_daemon (self->priv->conn),
+ self->priv->object_path, self);
+
+ tp_text_mixin_init (object, G_STRUCT_OFFSET (TpTestsTextChannelNull, text),
+ contact_repo);
+
+ tp_text_mixin_set_message_types (object,
+ TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
+ TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION,
+ TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE,
+ G_MAXUINT);
+
+ return object;
+}
+
+static void
+get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (object);
+
+ switch (property_id)
+ {
+ case PROP_OBJECT_PATH:
+ g_value_set_string (value, self->priv->object_path);
+ break;
+ case PROP_CHANNEL_TYPE:
+ g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_TEXT);
+ break;
+ case PROP_HANDLE_TYPE:
+ g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT);
+ break;
+ case PROP_HANDLE:
+ g_value_set_uint (value, self->priv->handle);
+ break;
+ case PROP_TARGET_ID:
+ {
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
+ self->priv->conn, TP_HANDLE_TYPE_CONTACT);
+
+ g_value_set_string (value,
+ tp_handle_inspect (contact_repo, self->priv->handle));
+ }
+ break;
+ case PROP_REQUESTED:
+ g_value_set_boolean (value, TRUE);
+ break;
+ case PROP_INITIATOR_HANDLE:
+ g_value_set_uint (value, self->priv->conn->self_handle);
+ break;
+ case PROP_INITIATOR_ID:
+ {
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
+ self->priv->conn, TP_HANDLE_TYPE_CONTACT);
+
+ g_value_set_string (value,
+ tp_handle_inspect (contact_repo, self->priv->conn->self_handle));
+ }
+ break;
+ case PROP_INTERFACES:
+ g_value_set_boxed (value, tp_tests_text_channel_null_interfaces);
+ break;
+ case PROP_CONNECTION:
+ g_value_set_object (value, self->priv->conn);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (object);
+
+ switch (property_id)
+ {
+ case PROP_OBJECT_PATH:
+ g_free (self->priv->object_path);
+ self->priv->object_path = g_value_dup_string (value);
+ break;
+ case PROP_HANDLE:
+ /* we don't ref it here because we don't necessarily have access to the
+ * contact repo yet - instead we ref it in the constructor.
+ */
+ self->priv->handle = g_value_get_uint (value);
+ break;
+ case PROP_HANDLE_TYPE:
+ case PROP_CHANNEL_TYPE:
+ /* these properties are writable in the interface, but not actually
+ * meaningfully changable on this channel, so we do nothing */
+ break;
+ case PROP_CONNECTION:
+ self->priv->conn = g_value_get_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+void
+tp_tests_text_channel_null_close (TpTestsTextChannelNull *self)
+{
+ if (!self->priv->closed)
+ {
+ self->priv->closed = TRUE;
+ tp_svc_channel_emit_closed (self);
+ tp_dbus_daemon_unregister_object (
+ tp_base_connection_get_dbus_daemon (self->priv->conn), self);
+ }
+}
+
+static void
+dispose (GObject *object)
+{
+ TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (object);
+
+ if (self->priv->disposed)
+ return;
+
+ self->priv->disposed = TRUE;
+ tp_tests_text_channel_null_close (self);
+
+ ((GObjectClass *) tp_tests_text_channel_null_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+ TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (object);
+ TpHandleRepoIface *contact_handles = tp_base_connection_get_handles
+ (self->priv->conn, TP_HANDLE_TYPE_CONTACT);
+
+ tp_handle_unref (contact_handles, self->priv->handle);
+ g_free (self->priv->object_path);
+
+ tp_text_mixin_finalize (object);
+
+ ((GObjectClass *) tp_tests_text_channel_null_parent_class)->finalize (object);
+}
+
+static void
+tp_tests_text_channel_null_class_init (TpTestsTextChannelNullClass *klass)
+{
+ GObjectClass *object_class = (GObjectClass *) klass;
+ GParamSpec *param_spec;
+
+ g_type_class_add_private (klass, sizeof (TpTestsTextChannelNullPrivate));
+
+ object_class->constructor = constructor;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ object_class->dispose = dispose;
+ object_class->finalize = finalize;
+
+ g_object_class_override_property (object_class, PROP_OBJECT_PATH,
+ "object-path");
+ g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
+ "channel-type");
+ g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
+ "handle-type");
+ g_object_class_override_property (object_class, PROP_HANDLE, "handle");
+
+ param_spec = g_param_spec_object ("connection", "TpBaseConnection object",
+ "Connection object that owns this channel",
+ TP_TYPE_BASE_CONNECTION,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
+
+ param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces",
+ "Additional Channel.Interface.* interfaces",
+ G_TYPE_STRV,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_INTERFACES, param_spec);
+
+ param_spec = g_param_spec_string ("target-id", "Peer's ID",
+ "The string obtained by inspecting the target handle",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_TARGET_ID, param_spec);
+
+ param_spec = g_param_spec_uint ("initiator-handle", "Initiator's handle",
+ "The contact who initiated the channel",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_INITIATOR_HANDLE,
+ param_spec);
+
+ param_spec = g_param_spec_string ("initiator-id", "Initiator's ID",
+ "The string obtained by inspecting the initiator-handle",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_INITIATOR_ID,
+ param_spec);
+
+ param_spec = g_param_spec_boolean ("requested", "Requested?",
+ "True if this channel was requested by the local user",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_REQUESTED, param_spec);
+
+ tp_text_mixin_class_init (object_class,
+ G_STRUCT_OFFSET (TpTestsTextChannelNullClass, text_class));
+}
+
+static void
+tp_tests_props_text_channel_getter_gobject_properties (GObject *object,
+ GQuark interface,
+ GQuark name,
+ GValue *value,
+ gpointer getter_data)
+{
+ TpTestsPropsTextChannel *self = TP_TESTS_PROPS_TEXT_CHANNEL (object);
+
+ g_hash_table_insert (self->dbus_property_interfaces_retrieved,
+ GUINT_TO_POINTER (interface), GUINT_TO_POINTER (interface));
+
+ tp_dbus_properties_mixin_getter_gobject_properties (object, interface, name,
+ value, getter_data);
+}
+
+static void
+props_finalize (GObject *object)
+{
+ TpTestsPropsTextChannel *self = TP_TESTS_PROPS_TEXT_CHANNEL (object);
+
+ g_hash_table_unref (self->dbus_property_interfaces_retrieved);
+
+ ((GObjectClass *) tp_tests_props_text_channel_parent_class)->finalize (object);
+}
+
+static void
+tp_tests_props_text_channel_class_init (TpTestsPropsTextChannelClass *klass)
+{
+ GObjectClass *object_class = (GObjectClass *) klass;
+ static TpDBusPropertiesMixinPropImpl channel_props[] = {
+ { "TargetHandleType", "handle-type", NULL },
+ { "TargetHandle", "handle", NULL },
+ { "ChannelType", "channel-type", NULL },
+ { "Interfaces", "interfaces", NULL },
+ { "TargetID", "target-id", NULL },
+ { "Requested", "requested", NULL },
+ { "InitiatorHandle", "initiator-handle", NULL },
+ { "InitiatorID", "initiator-id", NULL },
+ { NULL }
+ };
+ static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
+ { TP_IFACE_CHANNEL,
+ tp_tests_props_text_channel_getter_gobject_properties,
+ NULL,
+ channel_props,
+ },
+ { NULL }
+ };
+
+ object_class->finalize = props_finalize;
+
+ klass->dbus_properties_class.interfaces = prop_interfaces;
+ tp_dbus_properties_mixin_class_init (object_class,
+ G_STRUCT_OFFSET (TpTestsPropsTextChannelClass, dbus_properties_class));
+}
+
+static void
+tp_tests_props_group_text_channel_init (TpTestsPropsGroupTextChannel *self)
+{
+}
+
+static void
+group_constructed (GObject *self)
+{
+ TpBaseConnection *conn = TP_TESTS_TEXT_CHANNEL_NULL (self)->priv->conn;
+ void (*chain_up) (GObject *) =
+ ((GObjectClass *) tp_tests_props_group_text_channel_parent_class)->constructed;
+
+ if (chain_up != NULL)
+ chain_up (self);
+
+ tp_group_mixin_init (self,
+ G_STRUCT_OFFSET (TpTestsPropsGroupTextChannel, group),
+ tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT),
+ tp_base_connection_get_self_handle (conn));
+ tp_group_mixin_change_flags (self, TP_CHANNEL_GROUP_FLAG_PROPERTIES, 0);
+}
+
+static void
+group_finalize (GObject *self)
+{
+ tp_group_mixin_finalize (self);
+
+ ((GObjectClass *) tp_tests_props_group_text_channel_parent_class)->finalize (self);
+}
+
+static gboolean
+dummy_add_remove_member (GObject *obj,
+ TpHandle handle,
+ const gchar *message,
+ GError **error)
+{
+ return TRUE;
+}
+
+static void
+group_iface_props_getter (GObject *object,
+ GQuark interface,
+ GQuark name,
+ GValue *value,
+ gpointer getter_data)
+{
+ TpTestsPropsTextChannel *self = TP_TESTS_PROPS_TEXT_CHANNEL (object);
+
+ g_hash_table_insert (self->dbus_property_interfaces_retrieved,
+ GUINT_TO_POINTER (interface), GUINT_TO_POINTER (interface));
+
+ tp_group_mixin_get_dbus_property (object, interface, name, value, getter_data);
+}
+
+static void
+tp_tests_props_group_text_channel_class_init (TpTestsPropsGroupTextChannelClass *klass)
+{
+ GObjectClass *object_class = (GObjectClass *) klass;
+ static TpDBusPropertiesMixinPropImpl group_props[] = {
+ { "GroupFlags", NULL, NULL },
+ { "HandleOwners", NULL, NULL },
+ { "LocalPendingMembers", NULL, NULL },
+ { "Members", NULL, NULL },
+ { "RemotePendingMembers", NULL, NULL },
+ { "SelfHandle", NULL, NULL },
+ { NULL }
+ };
+
+ object_class->constructed = group_constructed;
+ object_class->finalize = group_finalize;
+
+ tp_group_mixin_class_init (object_class,
+ G_STRUCT_OFFSET (TpTestsPropsGroupTextChannelClass, group_class),
+ dummy_add_remove_member,
+ dummy_add_remove_member);
+ tp_dbus_properties_mixin_implement_interface (object_class,
+ TP_IFACE_QUARK_CHANNEL_INTERFACE_GROUP, group_iface_props_getter, NULL,
+ group_props);
+}
+
+static void
+channel_close (TpSvcChannel *iface,
+ DBusGMethodInvocation *context)
+{
+ TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (iface);
+
+ tp_tests_text_channel_null_close (self);
+ tp_svc_channel_return_from_close (context);
+}
+
+static void
+channel_get_channel_type (TpSvcChannel *iface,
+ DBusGMethodInvocation *context)
+{
+ TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (iface);
+
+ self->get_channel_type_called++;
+
+ tp_svc_channel_return_from_get_channel_type (context,
+ TP_IFACE_CHANNEL_TYPE_TEXT);
+}
+
+static void
+channel_get_handle (TpSvcChannel *iface,
+ DBusGMethodInvocation *context)
+{
+ TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (iface);
+
+ self->get_handle_called++;
+
+ tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_CONTACT,
+ self->priv->handle);
+}
+
+static void
+channel_get_interfaces (TpSvcChannel *iface,
+ DBusGMethodInvocation *context)
+{
+ TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (iface);
+
+ self->get_interfaces_called++;
+
+ tp_svc_channel_return_from_get_interfaces (context,
+ tp_tests_text_channel_null_interfaces);
+}
+
+static void
+channel_iface_init (gpointer iface,
+ gpointer data)
+{
+ TpSvcChannelClass *klass = iface;
+
+#define IMPLEMENT(x) tp_svc_channel_implement_##x (klass, channel_##x)
+ IMPLEMENT (close);
+ IMPLEMENT (get_channel_type);
+ IMPLEMENT (get_handle);
+ IMPLEMENT (get_interfaces);
+#undef IMPLEMENT
+}
+
+static void
+text_send (TpSvcChannelTypeText *iface,
+ guint type,
+ const gchar *text,
+ DBusGMethodInvocation *context)
+{
+ /* silently swallow the message */
+ tp_svc_channel_type_text_return_from_send (context);
+}
+
+static void
+text_iface_init (gpointer iface,
+ gpointer data)
+{
+ TpSvcChannelTypeTextClass *klass = iface;
+
+ tp_text_mixin_iface_init (iface, data);
+#define IMPLEMENT(x) tp_svc_channel_type_text_implement_##x (klass, text_##x)
+ IMPLEMENT (send);
+#undef IMPLEMENT
+}
+
+GHashTable *
+tp_tests_text_channel_get_props (TpTestsTextChannelNull *self)
+{
+ GHashTable *props;
+ TpHandleType handle_type;
+ TpHandle handle;
+ gchar *target_id;
+ gboolean requested;
+ TpHandle initiator_handle;
+ gchar *initiator_id;
+ GStrv interfaces;
+
+ g_object_get (self,
+ "handle-type", &handle_type,
+ "handle", &handle,
+ "target-id", &target_id,
+ "requested", &requested,
+ "initiator-handle", &initiator_handle,
+ "initiator-id", &initiator_id,
+ "interfaces", &interfaces,
+ NULL);
+
+ props = tp_asv_new (
+ TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_TEXT,
+ TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, handle_type,
+ TP_PROP_CHANNEL_TARGET_HANDLE, G_TYPE_UINT, handle,
+ TP_PROP_CHANNEL_TARGET_ID, G_TYPE_STRING, target_id,
+ TP_PROP_CHANNEL_REQUESTED, G_TYPE_BOOLEAN, requested,
+ TP_PROP_CHANNEL_INITIATOR_HANDLE, G_TYPE_UINT, initiator_handle,
+ TP_PROP_CHANNEL_INITIATOR_ID, G_TYPE_STRING, initiator_id,
+ TP_PROP_CHANNEL_INTERFACES, G_TYPE_STRV, interfaces,
+ NULL);
+
+ g_free (target_id);
+ g_free (initiator_id);
+ g_strfreev (interfaces);
+ return props;
+}
diff --git a/tests/lib/telepathy/contactlist/textchan-null.h b/tests/lib/telepathy/contactlist/textchan-null.h
new file mode 100644
index 0000000..583bec5
--- /dev/null
+++ b/tests/lib/telepathy/contactlist/textchan-null.h
@@ -0,0 +1,137 @@
+/*
+ * /dev/null as a text channel
+ *
+ * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved.
+ */
+
+#ifndef __TP_TESTS_TEXT_CHANNEL_NULL_H__
+#define __TP_TESTS_TEXT_CHANNEL_NULL_H__
+
+#include <glib-object.h>
+#include <telepathy-glib/base-connection.h>
+#include <telepathy-glib/text-mixin.h>
+#include <telepathy-glib/group-mixin.h>
+
+G_BEGIN_DECLS
+
+typedef struct _TpTestsTextChannelNull TpTestsTextChannelNull;
+typedef struct _TpTestsTextChannelNullClass TpTestsTextChannelNullClass;
+typedef struct _TpTestsTextChannelNullPrivate TpTestsTextChannelNullPrivate;
+
+GType tp_tests_text_channel_null_get_type (void);
+
+#define TP_TESTS_TYPE_TEXT_CHANNEL_NULL \
+ (tp_tests_text_channel_null_get_type ())
+#define TP_TESTS_TEXT_CHANNEL_NULL(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_TEXT_CHANNEL_NULL, \
+ TpTestsTextChannelNull))
+#define TP_TESTS_TEXT_CHANNEL_NULL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_TEXT_CHANNEL_NULL, \
+ TpTestsTextChannelNullClass))
+#define TP_TESTS_IS_TEXT_CHANNEL_NULL(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_TEXT_CHANNEL_NULL))
+#define TP_TESTS_IS_TEXT_CHANNEL_NULL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_TEXT_CHANNEL_NULL))
+#define TP_TESTS_TEXT_CHANNEL_NULL_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_TEXT_CHANNEL_NULL, \
+ TpTestsTextChannelNullClass))
+
+struct _TpTestsTextChannelNullClass {
+ GObjectClass parent_class;
+
+ TpTextMixinClass text_class;
+};
+
+struct _TpTestsTextChannelNull {
+ GObject parent;
+ TpTextMixin text;
+
+ guint get_handle_called;
+ guint get_interfaces_called;
+ guint get_channel_type_called;
+
+ TpTestsTextChannelNullPrivate *priv;
+};
+
+/* Subclass with D-Bus properties */
+
+typedef struct _TestPropsTextChannel TpTestsPropsTextChannel;
+typedef struct _TestPropsTextChannelClass TpTestsPropsTextChannelClass;
+
+struct _TestPropsTextChannel {
+ TpTestsTextChannelNull parent;
+
+ GHashTable *dbus_property_interfaces_retrieved;
+};
+
+struct _TestPropsTextChannelClass {
+ TpTestsTextChannelNullClass parent;
+
+ TpDBusPropertiesMixinClass dbus_properties_class;
+};
+
+GType tp_tests_props_text_channel_get_type (void);
+
+#define TP_TESTS_TYPE_PROPS_TEXT_CHANNEL \
+ (tp_tests_props_text_channel_get_type ())
+#define TP_TESTS_PROPS_TEXT_CHANNEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_PROPS_TEXT_CHANNEL, \
+ TpTestsPropsTextChannel))
+#define TP_TESTS_PROPS_TEXT_CHANNEL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_PROPS_TEXT_CHANNEL, \
+ TpTestsPropsTextChannelClass))
+#define TP_TESTS_IS_PROPS_TEXT_CHANNEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_PROPS_TEXT_CHANNEL))
+#define TP_TESTS_IS_PROPS_TEXT_CHANNEL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_PROPS_TEXT_CHANNEL))
+#define TP_TESTS_PROPS_TEXT_CHANNEL_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_PROPS_TEXT_CHANNEL, \
+ TpTestsPropsTextChannelClass))
+
+/* Subclass with D-Bus properties and Group */
+
+typedef struct _TestPropsGroupTextChannel TpTestsPropsGroupTextChannel;
+typedef struct _TestPropsGroupTextChannelClass TpTestsPropsGroupTextChannelClass;
+
+struct _TestPropsGroupTextChannel {
+ TpTestsPropsTextChannel parent;
+
+ TpGroupMixin group;
+};
+
+struct _TestPropsGroupTextChannelClass {
+ TpTestsPropsTextChannelClass parent;
+
+ TpGroupMixinClass group_class;
+};
+
+GType tp_tests_props_group_text_channel_get_type (void);
+
+#define TP_TESTS_TYPE_PROPS_GROUP_TEXT_CHANNEL \
+ (tp_tests_props_group_text_channel_get_type ())
+#define TP_TESTS_PROPS_GROUP_TEXT_CHANNEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_PROPS_GROUP_TEXT_CHANNEL, \
+ TpTestsPropsGroupTextChannel))
+#define TP_TESTS_PROPS_GROUP_TEXT_CHANNEL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_PROPS_GROUP_TEXT_CHANNEL, \
+ TpTestsPropsGroupTextChannelClass))
+#define TP_TESTS_IS_PROPS_GROUP_TEXT_CHANNEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_PROPS_GROUP_TEXT_CHANNEL))
+#define TP_TESTS_IS_PROPS_GROUP_TEXT_CHANNEL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_PROPS_GROUP_TEXT_CHANNEL))
+#define TP_TESTS_PROPS_GROUP_TEXT_CHANNEL_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_PROPS_GROUP_TEXT_CHANNEL, \
+ TpTestsPropsGroupTextChannelClass))
+
+void tp_tests_text_channel_null_close (TpTestsTextChannelNull *self);
+
+GHashTable * tp_tests_text_channel_get_props (TpTestsTextChannelNull *self);
+
+G_END_DECLS
+
+#endif /* #ifndef __TP_TESTS_TEXT_CHANNEL_NULL_H__ */
diff --git a/tests/lib/telepathy/contactlist/tp-test-contactlist.h b/tests/lib/telepathy/contactlist/tp-test-contactlist.h
index 2ce4b65..0d952d9 100644
--- a/tests/lib/telepathy/contactlist/tp-test-contactlist.h
+++ b/tests/lib/telepathy/contactlist/tp-test-contactlist.h
@@ -1,11 +1,10 @@
#ifndef __EXAMPLE_CONTACTLIST_H__
#define __EXAMPLE_CONTACTLIST_H__
-#include <account-manager.h>
-#include <account.h>
+#include <simple-account-manager.h>
+#include <simple-account.h>
#include <backend.h>
-#include <conn.h>
+#include <contacts-conn.h>
#include <contact-list-manager.h>
-#include <contact-list.h>
#endif /* __EXAMPLE_CONTACTLIST_H__ */
diff --git a/tests/telepathy/individual-properties.vala b/tests/telepathy/individual-properties.vala
index 8580739..12cd3ad 100644
--- a/tests/telepathy/individual-properties.vala
+++ b/tests/telepathy/individual-properties.vala
@@ -323,9 +323,9 @@ public class IndividualPropertiesTests : Folks.TestCase
/* set the alias through Telepathy and wait for it to hit our
* alias notification callback above */
-
var handle = (Handle) ((Tpf.Persona) persona).contact.handle;
- this.tp_backend.connection.manager.set_alias (handle, new_alias);
+ var conn = this.tp_backend.get_connection_for_handle (this._account_handle);
+ conn.change_aliases ({handle}, {new_alias});
}
assert (removed.size == 1);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]