From 109133c590822eb93fa9c8245fdb2f7347f5acf6 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 27 Mar 2012 18:05:12 +0200 Subject: [PATCH] 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(-) delete mode 100644 tests/lib/telepathy/contactlist/account-manager.h delete mode 100644 tests/lib/telepathy/contactlist/account.c delete mode 100644 tests/lib/telepathy/contactlist/account.h delete mode 100644 tests/lib/telepathy/contactlist/conn.c delete mode 100644 tests/lib/telepathy/contactlist/conn.h delete mode 100644 tests/lib/telepathy/contactlist/contact-list.c delete mode 100644 tests/lib/telepathy/contactlist/contact-list.h create mode 100644 tests/lib/telepathy/contactlist/contacts-conn.c create mode 100644 tests/lib/telepathy/contactlist/contacts-conn.h create mode 100644 tests/lib/telepathy/contactlist/debug.h rename tests/lib/telepathy/contactlist/{account-manager.c => simple-account-manager.c} (54%) create mode 100644 tests/lib/telepathy/contactlist/simple-account-manager.h create mode 100644 tests/lib/telepathy/contactlist/simple-account.c create mode 100644 tests/lib/telepathy/contactlist/simple-account.h create mode 100644 tests/lib/telepathy/contactlist/simple-conn.c create mode 100644 tests/lib/telepathy/contactlist/simple-conn.h create mode 100644 tests/lib/telepathy/contactlist/textchan-null.c create mode 100644 tests/lib/telepathy/contactlist/textchan-null.h 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/account-manager.h b/tests/lib/telepathy/contactlist/account-manager.h deleted file mode 100644 index 7487bd8..0000000 --- a/tests/lib/telepathy/contactlist/account-manager.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * account-manager.h - header for a simple account manager service. - * - * Copyright (C) 2007-2009 Collabora Ltd. - * 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.h. - */ - -#ifndef __TP_TESTS_ACCOUNT_MANAGER_H__ -#define __TP_TESTS_ACCOUNT_MANAGER_H__ - -#include -#include - - -G_BEGIN_DECLS - -typedef struct _TpTestsAccountManager TpTestsAccountManager; -typedef struct _TpTestsAccountManagerClass TpTestsAccountManagerClass; -typedef struct _TpTestsAccountManagerPrivate TpTestsAccountManagerPrivate; - -struct _TpTestsAccountManagerClass { - GObjectClass parent_class; - TpDBusPropertiesMixinClass dbus_props_class; -}; - -struct _TpTestsAccountManager { - GObject parent; - - TpTestsAccountManagerPrivate *priv; -}; - -GType tp_tests_account_manager_get_type (void); - -/* TYPE MACROS */ -#define TP_TESTS_TYPE_ACCOUNT_MANAGER \ - (tp_tests_account_manager_get_type ()) -#define TP_TESTS_ACCOUNT_MANAGER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_ACCOUNT_MANAGER, \ - TpTestsAccountManager)) -#define TP_TESTS_ACCOUNT_MANAGER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_ACCOUNT_MANAGER, \ - TpTestsAccountManagerClass)) -#define IS_TP_TESTS_ACCOUNT_MANAGER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_ACCOUNT_MANAGER)) -#define TP_TESTS_IS_ACCOUNT_MANAGER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_ACCOUNT_MANAGER)) -#define TP_TESTS_ACCOUNT_MANAGER_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_ACCOUNT_MANAGER, \ - TpTestsAccountManagerClass)) - -TpTestsAccountManager *tp_tests_account_manager_new (void); - -void tp_tests_account_manager_add_account (TpTestsAccountManager *self, - const gchar *account_path); -void tp_tests_account_manager_remove_account (TpTestsAccountManager *self, - const gchar *account_path); - -G_END_DECLS - -#endif /* #ifndef __TP_TESTS_ACCOUNT_MANAGER_H__ */ diff --git a/tests/lib/telepathy/contactlist/account.c b/tests/lib/telepathy/contactlist/account.c deleted file mode 100644 index 1410f51..0000000 --- a/tests/lib/telepathy/contactlist/account.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * account.c - a simple account service. - * - * Copyright (C) 2010 Collabora Ltd. - * - * 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.c. - */ - -#include "account.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -static void account_iface_init (gpointer, gpointer); - -G_DEFINE_TYPE_WITH_CODE (TpTestsAccount, - tp_tests_account, - G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_ACCOUNT, - account_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, - tp_dbus_properties_mixin_iface_init) - ) - -/* TP_IFACE_ACCOUNT is implied */ -static const char *ACCOUNT_INTERFACES[] = { 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, -}; - -struct _TpTestsAccountPrivate -{ - gchar *connection_path; -}; - -static void -account_iface_init (gpointer klass, - gpointer unused G_GNUC_UNUSED) -{ -#define IMPLEMENT(x) tp_svc_account_implement_##x (\ - klass, tp_tests_account_##x) - /* TODO */ -#undef IMPLEMENT -} - - -static void -tp_tests_account_init (TpTestsAccount *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TESTS_TYPE_ACCOUNT, - TpTestsAccountPrivate); -} - -static void -tp_tests_account_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *spec) -{ - GValueArray *presence; - TpTestsAccountPrivate *priv = TP_TESTS_ACCOUNT (object)->priv; - - presence = tp_value_array_build (3, - G_TYPE_UINT, TP_CONNECTION_PRESENCE_TYPE_AVAILABLE, - G_TYPE_STRING, "available", - G_TYPE_STRING, "", - G_TYPE_INVALID); - - 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, TRUE); - 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_set_boxed (value, presence); - break; - case PROP_CONNECT_AUTO: - g_value_set_boolean (value, FALSE); - break; - case PROP_CONNECTION: - g_value_set_boxed (value, 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_set_boxed (value, presence); - break; - case PROP_REQUESTED_PRESENCE: - g_value_set_boxed (value, presence); - break; - case PROP_NORMALIZED_NAME: - g_value_set_string (value, ""); - break; - case PROP_HAS_BEEN_ONLINE: - g_value_set_boolean (value, TRUE); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec); - break; - } - - g_boxed_free (TP_STRUCT_TYPE_SIMPLE_PRESENCE, presence); -} - -static void -tp_tests_account_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *spec) -{ - TpTestsAccountPrivate *priv = TP_TESTS_ACCOUNT (object)->priv; - - switch (property_id) { - case PROP_CONNECTION: - priv->connection_path = g_strdup (g_value_get_boxed (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec); - break; - } -} - -static void -tp_tests_account_finalize (GObject *object) -{ - TpTestsAccountPrivate *priv = TP_TESTS_ACCOUNT (object)->priv; - - g_free (priv->connection_path); - - G_OBJECT_CLASS (tp_tests_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_account_class_init (TpTestsAccountClass *klass) -{ - GObjectClass *object_class = (GObjectClass *) klass; - GParamSpec *param_spec; - - static TpDBusPropertiesMixinPropImpl a_props[] = { - { "Interfaces", (gpointer) "interfaces", NULL }, - { "DisplayName", (gpointer) "display-name", NULL }, - { "Icon", (gpointer) "icon", NULL }, - { "Valid", (gpointer) "valid", NULL }, - { "Enabled", (gpointer) "enabled", NULL }, - { "Nickname", (gpointer) "nickname", NULL }, - { "Parameters", (gpointer) "parameters", NULL }, - { "AutomaticPresence", (gpointer) "automatic-presence", NULL }, - { "ConnectAutomatically", (gpointer) "connect-automatically", NULL }, - { "Connection", (gpointer) "connection", NULL }, - { "ConnectionStatus", (gpointer) "connection-status", NULL }, - { "ConnectionStatusReason", (gpointer) "connection-status-reason", NULL }, - { "CurrentPresence", (gpointer) "current-presence", NULL }, - { "RequestedPresence", (gpointer) "requested-presence", NULL }, - { "NormalizedName", (gpointer) "normalized-name", NULL }, - { "HasBeenOnline", (gpointer) "has-been-online", NULL }, - { NULL } - }; - - static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { - { TP_IFACE_ACCOUNT, - tp_dbus_properties_mixin_getter_gobject_properties, - NULL, - a_props - }, - { NULL }, - }; - - g_type_class_add_private (klass, sizeof (TpTestsAccountPrivate)); - object_class->get_property = tp_tests_account_get_property; - object_class->set_property = tp_tests_account_set_property; - object_class->finalize = tp_tests_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_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_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); - - klass->dbus_props_class.interfaces = prop_interfaces; - tp_dbus_properties_mixin_class_init (object_class, - G_STRUCT_OFFSET (TpTestsAccountClass, dbus_props_class)); -} - -TpTestsAccount * -tp_tests_account_new (const gchar *connection_path) -{ - return g_object_new (TP_TESTS_TYPE_ACCOUNT, - "connection", connection_path, NULL); -} diff --git a/tests/lib/telepathy/contactlist/account.h b/tests/lib/telepathy/contactlist/account.h deleted file mode 100644 index 1ecff42..0000000 --- a/tests/lib/telepathy/contactlist/account.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * account.h - header for a simple account service. - * - * Copyright (C) 2010 Collabora Ltd. - * - * 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.h. - */ - -#ifndef __TP_TESTS_ACCOUNT_H__ -#define __TP_TESTS_ACCOUNT_H__ - -#include -#include - - -G_BEGIN_DECLS - -typedef struct _TpTestsAccount TpTestsAccount; -typedef struct _TpTestsAccountClass TpTestsAccountClass; -typedef struct _TpTestsAccountPrivate TpTestsAccountPrivate; - -struct _TpTestsAccountClass { - GObjectClass parent_class; - TpDBusPropertiesMixinClass dbus_props_class; -}; - -struct _TpTestsAccount { - GObject parent; - - TpTestsAccountPrivate *priv; -}; - -GType tp_tests_account_get_type (void); - -/* TYPE MACROS */ -#define TP_TESTS_TYPE_ACCOUNT \ - (tp_tests_account_get_type ()) -#define TP_TESTS_ACCOUNT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_ACCOUNT, \ - TpTestsAccount)) -#define TP_TESTS_ACCOUNT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_ACCOUNT, \ - TpTestsAccountClass)) -#define TP_TESTS_IS_ACCOUNT(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_ACCOUNT)) -#define TP_TESTS_IS_ACCOUNT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_ACCOUNT)) -#define TP_TESTS_ACCOUNT_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_ACCOUNT, \ - TpTestsAccountClass)) - -TpTestsAccount *tp_tests_account_new (const gchar *connection_path); - -G_END_DECLS - -#endif /* #ifndef __TP_TESTS_ACCOUNT_H__ */ 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 #include -#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 #include -#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/conn.c b/tests/lib/telepathy/contactlist/conn.c deleted file mode 100644 index 9a403d0..0000000 --- a/tests/lib/telepathy/contactlist/conn.c +++ /dev/null @@ -1,972 +0,0 @@ -/* - * conn.c - an tp_test connection - * - * Copyright © 2007-2011 Collabora Ltd. - * 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 - * notice and this notice are preserved. - */ - - -#include "config.h" - -#include "conn.h" - -#include - -#include - -#include -#include -#include - -#include "contact-list-manager.h" - -static void init_aliasing (gpointer, gpointer); -static void init_contact_info (gpointer, gpointer); - -G_DEFINE_TYPE_WITH_CODE (TpTestsContactListConnection, - tp_tests_contact_list_connection, - TP_TYPE_BASE_CONNECTION, - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING, - init_aliasing); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS, - tp_contacts_mixin_iface_init); - 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_CONTACT_INFO, - init_contact_info)) - -enum -{ - PROP_ACCOUNT = 1, - PROP_SIMULATION_DELAY, - PROP_MANAGER, - PROP_PUBLISH_FLAGS, - PROP_SUBSCRIBE_FLAGS, - N_PROPS -}; - -struct _TpTestsContactListConnectionPrivate -{ - gchar *account; - guint simulation_delay; - TpTestsContactListManager *list_manager; - gboolean away; - TpChannelGroupFlags publish_flags; - TpChannelGroupFlags subscribe_flags; -}; - -static TpChannelGroupFlags default_group_flags = - TP_CHANNEL_GROUP_FLAG_CAN_ADD | - TP_CHANNEL_GROUP_FLAG_CAN_REMOVE | - TP_CHANNEL_GROUP_FLAG_MEMBERS_CHANGED_DETAILED; - -static void -tp_tests_contact_list_connection_init (TpTestsContactListConnection *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - TP_TESTS_TYPE_CONTACT_LIST_CONNECTION, - TpTestsContactListConnectionPrivate); -} - -static void -get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *spec) -{ - TpTestsContactListConnection *self = - TP_TESTS_CONTACT_LIST_CONNECTION (object); - - switch (property_id) - { - case PROP_ACCOUNT: - g_value_set_string (value, self->priv->account); - break; - - case PROP_MANAGER: - g_value_set_object (value, self->priv->list_manager); - break; - - case PROP_PUBLISH_FLAGS: - g_value_set_uint (value, self->priv->publish_flags); - break; - - case PROP_SUBSCRIBE_FLAGS: - g_value_set_uint (value, self->priv->subscribe_flags); - break; - - case PROP_SIMULATION_DELAY: - g_value_set_uint (value, self->priv->simulation_delay); - 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) -{ - TpTestsContactListConnection *self = - TP_TESTS_CONTACT_LIST_CONNECTION (object); - - switch (property_id) - { - case PROP_ACCOUNT: - g_free (self->priv->account); - self->priv->account = g_value_dup_string (value); - break; - - case PROP_PUBLISH_FLAGS: - self->priv->publish_flags = g_value_get_uint (value); - break; - - case PROP_SUBSCRIBE_FLAGS: - self->priv->subscribe_flags = g_value_get_uint (value); - break; - - case PROP_SIMULATION_DELAY: - self->priv->simulation_delay = g_value_get_uint (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec); - } -} - -static void -finalize (GObject *object) -{ - TpTestsContactListConnection *self = - TP_TESTS_CONTACT_LIST_CONNECTION (object); - - tp_contacts_mixin_finalize (object); - g_free (self->priv->account); - - G_OBJECT_CLASS (tp_tests_contact_list_connection_parent_class)->finalize ( - object); -} - -/** - * tp_tests_contact_list_connection_get_manager: - * @self: the connection - * - * Returns: (transfer none): the contact list manager or %NULL. - */ -TpTestsContactListManager * -tp_tests_contact_list_connection_get_manager (TpTestsContactListConnection *self) -{ - g_return_val_if_fail (TP_TESTS_IS_CONTACT_LIST_CONNECTION (self), NULL); - - return self->priv->list_manager; -} - -static gchar * -get_unique_connection_name (TpBaseConnection *conn) -{ - TpTestsContactListConnection *self = TP_TESTS_CONTACT_LIST_CONNECTION (conn); - - return g_strdup_printf ("%s@%p", self->priv->account, self); -} - -gchar * -tp_tests_contact_list_normalize_contact (TpHandleRepoIface *repo, - const gchar *id, - gpointer context, - GError **error) -{ - if (id == NULL || id[0] == '\0') - { - g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_HANDLE, - "Contact ID must not be empty"); - return NULL; - } - - return g_utf8_normalize (id, -1, G_NORMALIZE_ALL_COMPOSE); -} - -static gchar * -tp_tests_contact_list_normalize_group (TpHandleRepoIface *repo, - const gchar *id, - gpointer context, - GError **error) -{ - if (id == NULL || id[0] == '\0') - { - g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_HANDLE, - "Contact group name cannot be empty"); - return NULL; - } - - return g_utf8_normalize (id, -1, G_NORMALIZE_ALL_COMPOSE); -} - -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_contact_list_normalize_contact, NULL); - - repos[TP_HANDLE_TYPE_LIST] = tp_static_handle_repo_new - (TP_HANDLE_TYPE_LIST, tp_tests_contact_lists ()); - - repos[TP_HANDLE_TYPE_GROUP] = tp_dynamic_handle_repo_new - (TP_HANDLE_TYPE_GROUP, tp_tests_contact_list_normalize_group, NULL); -} - -static void -alias_updated_cb (TpTestsContactListManager *manager, - TpHandle contact, - TpTestsContactListConnection *self) -{ - GPtrArray *aliases; - GValueArray *pair; - - pair = g_value_array_new (2); - g_value_array_append (pair, NULL); - g_value_array_append (pair, NULL); - g_value_init (pair->values + 0, G_TYPE_UINT); - g_value_init (pair->values + 1, G_TYPE_STRING); - g_value_set_uint (pair->values + 0, contact); - g_value_set_string (pair->values + 1, - tp_tests_contact_list_manager_get_alias (manager, contact)); - - aliases = g_ptr_array_sized_new (1); - g_ptr_array_add (aliases, pair); - - tp_svc_connection_interface_aliasing_emit_aliases_changed (self, aliases); - - g_ptr_array_free (aliases, TRUE); - g_value_array_free (pair); -} - -static void -contact_info_updated_cb (TpTestsContactListManager *manager, - TpHandle contact, - TpTestsContactListConnection *self) -{ - GPtrArray *contact_info = tp_tests_contact_list_manager_get_contact_info ( - self->priv->list_manager, contact); - - if (contact_info != NULL) - { - tp_svc_connection_interface_contact_info_emit_contact_info_changed (self, - contact, contact_info); - } -} - -static void -presence_updated_cb (TpTestsContactListManager *manager, - TpHandle contact, - TpTestsContactListConnection *self) -{ - TpBaseConnection *base = (TpBaseConnection *) self; - TpPresenceStatus *status; - - /* we ignore the presence indicated by the contact list for our own handle */ - if (contact == base->self_handle) - return; - - status = tp_presence_status_new ( - tp_tests_contact_list_manager_get_presence (manager, contact), - NULL); - tp_presence_mixin_emit_one_presence_update ((GObject *) self, - contact, status); - tp_presence_status_free (status); -} - -static GPtrArray * -create_channel_managers (TpBaseConnection *conn) -{ - TpTestsContactListConnection *self = - TP_TESTS_CONTACT_LIST_CONNECTION (conn); - GPtrArray *ret = g_ptr_array_sized_new (1); - - self->priv->list_manager = - TP_TESTS_CONTACT_LIST_MANAGER (g_object_new ( - TP_TESTS_TYPE_CONTACT_LIST_MANAGER, - "connection", conn, - "simulation-delay", self->priv->simulation_delay, - NULL)); - - g_signal_connect (self->priv->list_manager, "alias-updated", - G_CALLBACK (alias_updated_cb), self); - g_signal_connect (self->priv->list_manager, "contact-info-updated", - G_CALLBACK (contact_info_updated_cb), self); - g_signal_connect (self->priv->list_manager, "presence-updated", - G_CALLBACK (presence_updated_cb), self); - - g_ptr_array_add (ret, self->priv->list_manager); - - return ret; -} - -static gboolean -start_connecting (TpBaseConnection *conn, - GError **error) -{ - TpTestsContactListConnection *self = TP_TESTS_CONTACT_LIST_CONNECTION (conn); - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn, - TP_HANDLE_TYPE_CONTACT); - - /* In a real connection manager we'd ask the underlying implementation to - * start connecting, then go to state CONNECTED when finished, but here - * we can do it immediately. */ - - conn->self_handle = tp_handle_ensure (contact_repo, self->priv->account, - NULL, error); - - if (conn->self_handle == 0) - return FALSE; - - tp_base_connection_change_status (conn, TP_CONNECTION_STATUS_CONNECTED, - TP_CONNECTION_STATUS_REASON_REQUESTED); - - return TRUE; -} - -static void -shut_down (TpBaseConnection *conn) -{ - /* In a real connection manager we'd ask the underlying implementation to - * start shutting down, then call this function when finished, but here - * we can do it immediately. */ - tp_base_connection_finish_shutdown (conn); -} - -static void -aliasing_fill_contact_attributes (GObject *object, - const GArray *contacts, - GHashTable *attributes) -{ - TpTestsContactListConnection *self = - TP_TESTS_CONTACT_LIST_CONNECTION (object); - guint i; - - for (i = 0; i < contacts->len; i++) - { - TpHandle contact = g_array_index (contacts, guint, i); - - tp_contacts_mixin_set_contact_attribute (attributes, contact, - TP_TOKEN_CONNECTION_INTERFACE_ALIASING_ALIAS, - tp_g_value_slice_new_string ( - tp_tests_contact_list_manager_get_alias (self->priv->list_manager, - contact))); - } -} - -static void -contact_info_fill_contact_attributes (GObject *object, - const GArray *contacts, - GHashTable *attributes_hash) -{ - TpTestsContactListConnection *self = TP_TESTS_CONTACT_LIST_CONNECTION (object); - guint i; - - for (i = 0; i < contacts->len; i++) - { - TpHandle contact = g_array_index (contacts, TpHandle, i); - GPtrArray *contact_info = tp_tests_contact_list_manager_get_contact_info ( - self->priv->list_manager, contact); - if (contact_info != NULL) - { - GValue *val = tp_g_value_slice_new_boxed ( - TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST, contact_info); - - tp_contacts_mixin_set_contact_attribute (attributes_hash, - contact, - TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO "/info", val); - } - } -} - -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 -constructed (GObject *object) -{ - TpBaseConnection *base = TP_BASE_CONNECTION (object); - void (*chain_up) (GObject *) = - G_OBJECT_CLASS (tp_tests_contact_list_connection_parent_class)->constructed; - - if (chain_up != NULL) - chain_up (object); - - tp_contacts_mixin_init (object, - G_STRUCT_OFFSET (TpTestsContactListConnection, contacts_mixin)); - tp_base_connection_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_CONTACT_INFO, - contact_info_fill_contact_attributes); - - tp_presence_mixin_init (object, - G_STRUCT_OFFSET (TpTestsContactListConnection, presence_mixin)); - tp_presence_mixin_simple_presence_register_with_contacts_mixin (object); -} - -static gboolean -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 * -get_contact_statuses (GObject *object, - const GArray *contacts, - GError **error) -{ - TpTestsContactListConnection *self = - TP_TESTS_CONTACT_LIST_CONNECTION (object); - TpBaseConnection *base = TP_BASE_CONNECTION (object); - guint i; - GHashTable *result = g_hash_table_new_full (g_direct_hash, g_direct_equal, - NULL, (GDestroyNotify) tp_presence_status_free); - - for (i = 0; i < contacts->len; i++) - { - TpHandle contact = g_array_index (contacts, guint, i); - TpTestsContactListPresence presence; - GHashTable *parameters; - - /* we get our own status from the connection, and everyone else's status - * from the contact lists */ - if (contact == base->self_handle) - { - presence = (self->priv->away ? TP_TESTS_CONTACT_LIST_PRESENCE_AWAY - : TP_TESTS_CONTACT_LIST_PRESENCE_AVAILABLE); - } - else - { - presence = tp_tests_contact_list_manager_get_presence ( - self->priv->list_manager, contact); - } - - parameters = g_hash_table_new_full (g_str_hash, - g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); - g_hash_table_insert (result, GUINT_TO_POINTER (contact), - tp_presence_status_new (presence, parameters)); - g_hash_table_destroy (parameters); - } - - return result; -} - -static gboolean -set_own_status (GObject *object, - const TpPresenceStatus *status, - GError **error) -{ - TpTestsContactListConnection *self = - TP_TESTS_CONTACT_LIST_CONNECTION (object); - TpBaseConnection *base = TP_BASE_CONNECTION (object); - GHashTable *presences; - - if (status->index == TP_TESTS_CONTACT_LIST_PRESENCE_AWAY) - { - if (self->priv->away) - return TRUE; - - self->priv->away = TRUE; - } - else - { - if (!self->priv->away) - return TRUE; - - self->priv->away = FALSE; - } - - presences = g_hash_table_new_full (g_direct_hash, g_direct_equal, - NULL, NULL); - g_hash_table_insert (presences, GUINT_TO_POINTER (base->self_handle), - (gpointer) status); - tp_presence_mixin_emit_presence_update (object, presences); - g_hash_table_destroy (presences); - return TRUE; -} - -static void -tp_tests_contact_list_connection_class_init ( - TpTestsContactListConnectionClass *klass) -{ - static const gchar *interfaces_always_present[] = { - TP_IFACE_CONNECTION_INTERFACE_ALIASING, - TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO, - TP_IFACE_CONNECTION_INTERFACE_CONTACTS, - TP_IFACE_CONNECTION_INTERFACE_PRESENCE, - TP_IFACE_CONNECTION_INTERFACE_REQUESTS, - TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE, - NULL }; - static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { - { TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO, - conn_contact_info_properties_getter, - NULL, - conn_contact_info_properties, - }, - { NULL } - }; - - TpBaseConnectionClass *base_class = (TpBaseConnectionClass *) klass; - GObjectClass *object_class = (GObjectClass *) klass; - GParamSpec *param_spec; - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->constructed = constructed; - object_class->finalize = finalize; - g_type_class_add_private (klass, - sizeof (TpTestsContactListConnectionPrivate)); - - base_class->create_handle_repos = create_handle_repos; - base_class->get_unique_connection_name = get_unique_connection_name; - base_class->create_channel_managers = create_channel_managers; - 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_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); - g_object_class_install_property (object_class, PROP_ACCOUNT, param_spec); - - param_spec = g_param_spec_object ("manager", "TpTestsContactListManager", - "TpTestsContactListManager object that owns this channel", - TP_TESTS_TYPE_CONTACT_LIST_MANAGER, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_MANAGER, param_spec); - - param_spec = g_param_spec_uint ("publish-flags", "publish channel flags", - "'publish' channel group capabilities flags", - 0, ~0, default_group_flags, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_PUBLISH_FLAGS, - param_spec); - - param_spec = g_param_spec_uint ("subscribe-flags", "subscribe channel flags", - "'subscribe' channel group capabilities flags", - 0, ~0, default_group_flags, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_SUBSCRIBE_FLAGS, - 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); - - tp_contacts_mixin_class_init (object_class, - G_STRUCT_OFFSET (TpTestsContactListConnectionClass, contacts_mixin)); - tp_presence_mixin_class_init (object_class, - G_STRUCT_OFFSET (TpTestsContactListConnectionClass, presence_mixin), - status_available, get_contact_statuses, set_own_status, - tp_tests_contact_list_presence_statuses ()); - 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 (TpTestsContactListConnectionClass, properties_class)); -} - -static void -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, - TP_CONNECTION_ALIAS_FLAG_USER_SET); -} - -static void -get_aliases (TpSvcConnectionInterfaceAliasing *aliasing, - const GArray *contacts, - DBusGMethodInvocation *context) -{ - TpTestsContactListConnection *self = - TP_TESTS_CONTACT_LIST_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 contact = g_array_index (contacts, TpHandle, i); - const gchar *alias = tp_tests_contact_list_manager_get_alias ( - self->priv->list_manager, contact); - - g_hash_table_insert (result, GUINT_TO_POINTER (contact), - (gchar *) alias); - } - - tp_svc_connection_interface_aliasing_return_from_get_aliases (context, - result); - g_hash_table_destroy (result); -} - -static void -request_aliases (TpSvcConnectionInterfaceAliasing *aliasing, - const GArray *contacts, - DBusGMethodInvocation *context) -{ - TpTestsContactListConnection *self = - TP_TESTS_CONTACT_LIST_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 contact = g_array_index (contacts, TpHandle, i); - const gchar *alias = tp_tests_contact_list_manager_get_alias ( - self->priv->list_manager, contact); - - 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 -set_aliases (TpSvcConnectionInterfaceAliasing *aliasing, - GHashTable *aliases, - DBusGMethodInvocation *context) -{ - TpTestsContactListConnection *self = - TP_TESTS_CONTACT_LIST_CONNECTION (aliasing); - TpBaseConnection *base = TP_BASE_CONNECTION (aliasing); - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base, - TP_HANDLE_TYPE_CONTACT); - GHashTableIter iter; - gpointer key, value; - - g_hash_table_iter_init (&iter, aliases); - - while (g_hash_table_iter_next (&iter, &key, &value)) - { - GError *error = NULL; - - if (!tp_handle_is_valid (contact_repo, GPOINTER_TO_UINT (key), - &error)) - { - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - } - - g_hash_table_iter_init (&iter, aliases); - - while (g_hash_table_iter_next (&iter, &key, &value)) - { - tp_tests_contact_list_manager_set_alias (self->priv->list_manager, - GPOINTER_TO_UINT (key), value); - } - - tp_svc_connection_interface_aliasing_return_from_set_aliases (context); -} - -static void -init_aliasing (gpointer iface, - gpointer iface_data G_GNUC_UNUSED) -{ - TpSvcConnectionInterfaceAliasingClass *klass = iface; - -#define IMPLEMENT(x) tp_svc_connection_interface_aliasing_implement_##x (\ - klass, x) - IMPLEMENT(get_alias_flags); - IMPLEMENT(request_aliases); - IMPLEMENT(get_aliases); - IMPLEMENT(set_aliases); -#undef IMPLEMENT -} - -static void -get_contact_info ( - TpSvcConnectionInterfaceContactInfo *iface, - const GArray *contacts, - DBusGMethodInvocation *context) -{ - TpTestsContactListConnection *self = TP_TESTS_CONTACT_LIST_CONNECTION (iface); - TpBaseConnection *base = (TpBaseConnection *) self; - TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, - TP_HANDLE_TYPE_CONTACT); - GError *error = NULL; - guint i; - GHashTable *ret; - - TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (TP_BASE_CONNECTION (iface), - context); - - if (!tp_handles_are_valid (contact_handles, contacts, FALSE, &error)) - { - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - ret = dbus_g_type_specialized_construct (TP_HASH_TYPE_CONTACT_INFO_MAP); - - for (i = 0; i < contacts->len; i++) - { - TpHandle contact = g_array_index (contacts, TpHandle, i); - GPtrArray *contact_info = tp_tests_contact_list_manager_get_contact_info ( - self->priv->list_manager, contact); - if (contact_info != NULL) - { - g_hash_table_insert (ret, GUINT_TO_POINTER (contact), - g_boxed_copy (TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST, - contact_info)); - } - } - - tp_svc_connection_interface_contact_info_return_from_get_contact_info ( - context, ret); - - g_boxed_free (TP_HASH_TYPE_CONTACT_INFO_MAP, ret); -} - -static void -refresh_contact_info (TpSvcConnectionInterfaceContactInfo *iface, - const GArray *contacts, - DBusGMethodInvocation *context) -{ - TpTestsContactListConnection *self = TP_TESTS_CONTACT_LIST_CONNECTION (iface); - guint i; - - for (i = 0; i < contacts->len; i++) - { - TpHandle contact = g_array_index (contacts, TpHandle, i); - GPtrArray *contact_info; - - contact_info = tp_tests_contact_list_manager_get_contact_info ( - self->priv->list_manager, contact); - - if (contact_info != NULL) - { - tp_svc_connection_interface_contact_info_emit_contact_info_changed ( - iface, contact, contact_info); - } - } -} - -static void -_return_from_request_contact_info (TpTestsContactListConnection *self, - guint contact, - DBusGMethodInvocation *context) -{ - GError *error = NULL; - GPtrArray *contact_info; - - contact_info = tp_tests_contact_list_manager_get_contact_info ( - self->priv->list_manager, contact); - - if (contact_info == NULL) - { - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - tp_svc_connection_interface_contact_info_return_from_request_contact_info ( - context, contact_info); -} - -static void -request_contact_info (TpSvcConnectionInterfaceContactInfo *iface, - guint contact, - DBusGMethodInvocation *context) -{ - TpTestsContactListConnection *self = TP_TESTS_CONTACT_LIST_CONNECTION (iface); - TpBaseConnection *base = (TpBaseConnection *) self; - TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, - TP_HANDLE_TYPE_CONTACT); - GError *err = NULL; - - TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); - - if (!tp_handle_is_valid (contact_handles, contact, &err)) - { - dbus_g_method_return_error (context, err); - g_error_free (err); - return; - } - - _return_from_request_contact_info (self, contact, context); -} - -static void -set_contact_info (TpSvcConnectionInterfaceContactInfo *iface, - const GPtrArray *contact_info, - DBusGMethodInvocation *context) -{ - TpTestsContactListConnection *self = TP_TESTS_CONTACT_LIST_CONNECTION (iface); - GError *error = NULL; - - if (contact_info == NULL) - { - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - tp_tests_contact_list_manager_set_contact_info (self->priv->list_manager, - contact_info); - - tp_svc_connection_interface_contact_info_return_from_set_contact_info ( - context); -} - -static void -init_contact_info (gpointer iface, - gpointer iface_data G_GNUC_UNUSED) -{ - TpSvcConnectionInterfaceContactInfoClass *klass = iface; - -#define IMPLEMENT(x) tp_svc_connection_interface_contact_info_implement_##x (\ - klass, x) - IMPLEMENT(get_contact_info); - IMPLEMENT(refresh_contact_info); - IMPLEMENT(request_contact_info); - IMPLEMENT(set_contact_info); -#undef IMPLEMENT -} - -TpTestsContactListConnection * -tp_tests_contact_list_connection_new (const gchar *account, - const gchar *protocol, - TpChannelGroupFlags publish_flags, - TpChannelGroupFlags subscribe_flags) -{ - if (publish_flags == 0) - publish_flags = default_group_flags; - - if (subscribe_flags == 0) - subscribe_flags = default_group_flags; - - return g_object_new (TP_TESTS_TYPE_CONTACT_LIST_CONNECTION, - "account", account, - "protocol", protocol, - "publish-flags", publish_flags, - "subscribe-flags", subscribe_flags, - NULL); -} diff --git a/tests/lib/telepathy/contactlist/conn.h b/tests/lib/telepathy/contactlist/conn.h deleted file mode 100644 index cbb6451..0000000 --- a/tests/lib/telepathy/contactlist/conn.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * conn.h - header for an example connection - * - * Copyright © 2007-2009 Collabora Ltd. - * Copyright © 2007-2009 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_CONTACT_LIST_CONN_H__ -#define __TP_TESTS_CONTACT_LIST_CONN_H__ - -#include -#include -#include -#include - -#include "contact-list-manager.h" - -G_BEGIN_DECLS - -typedef struct _TpTestsContactListConnection TpTestsContactListConnection; -typedef struct _TpTestsContactListConnectionClass - TpTestsContactListConnectionClass; -typedef struct _TpTestsContactListConnectionPrivate - TpTestsContactListConnectionPrivate; - -struct _TpTestsContactListConnectionClass { - TpBaseConnectionClass parent_class; - TpDBusPropertiesMixinClass properties_class; - TpPresenceMixinClass presence_mixin; - TpContactsMixinClass contacts_mixin; -}; - -struct _TpTestsContactListConnection { - TpBaseConnection parent; - TpPresenceMixin presence_mixin; - TpContactsMixin contacts_mixin; - - TpTestsContactListConnectionPrivate *priv; -}; - -GType tp_tests_contact_list_connection_get_type (void); - -#define TP_TESTS_TYPE_CONTACT_LIST_CONNECTION \ - (tp_tests_contact_list_connection_get_type ()) -#define TP_TESTS_CONTACT_LIST_CONNECTION(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_CONTACT_LIST_CONNECTION, \ - TpTestsContactListConnection)) -#define TP_TESTS_CONTACT_LIST_CONNECTION_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_CONTACT_LIST_CONNECTION, \ - TpTestsContactListConnectionClass)) -#define TP_TESTS_IS_CONTACT_LIST_CONNECTION(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_CONTACT_LIST_CONNECTION)) -#define TP_TESTS_IS_CONTACT_LIST_CONNECTION_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_CONTACT_LIST_CONNECTION)) -#define TP_TESTS_CONTACT_LIST_CONNECTION_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_CONTACT_LIST_CONNECTION, \ - TpTestsContactListConnectionClass)) - -TpTestsContactListManager *tp_tests_contact_list_connection_get_manager ( - TpTestsContactListConnection *self); - -gchar *tp_tests_contact_list_normalize_contact (TpHandleRepoIface *repo, - const gchar *id, gpointer context, GError **error); - -TpTestsContactListConnection *tp_tests_contact_list_connection_new ( - const gchar *account, const gchar *protocol, - TpChannelGroupFlags publish_flags, TpChannelGroupFlags subscribe_flags); - -G_END_DECLS - -#endif 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. - * Copyright © 2007-2009 Nokia Corporation + * Copyright © 2007-2010 Collabora Ltd. + * 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 - -#include - #include -#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. - * Copyright © 2007-2009 Nokia Corporation + * Copyright © 2007-2010 Collabora Ltd. + * 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 - -#include -#include -#include +#include 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/contact-list.c b/tests/lib/telepathy/contactlist/contact-list.c deleted file mode 100644 index 4f27b29..0000000 --- a/tests/lib/telepathy/contactlist/contact-list.c +++ /dev/null @@ -1,632 +0,0 @@ -/* - * An example ContactList channel with handle type LIST or GROUP - * - * Copyright © 2009 Collabora Ltd. - * Copyright © 2009 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 "contact-list.h" - -#include -#include -#include -#include - -#include "contact-list-manager.h" - -static void channel_iface_init (gpointer iface, gpointer data); -static void list_channel_iface_init (gpointer iface, gpointer data); -static void group_channel_iface_init (gpointer iface, gpointer data); - -/* Abstract base class */ -G_DEFINE_TYPE_WITH_CODE (TpTestsContactListBase, tp_tests_contact_list_base, - G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_CONTACT_LIST, NULL); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP, - tp_group_mixin_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, - tp_dbus_properties_mixin_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_EXPORTABLE_CHANNEL, NULL); - G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL)) - -/* Subclass for handle type LIST */ -G_DEFINE_TYPE_WITH_CODE (TpTestsContactList, tp_tests_contact_list, - TP_TESTS_TYPE_CONTACT_LIST_BASE, - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, list_channel_iface_init)) - -/* Subclass for handle type GROUP */ -G_DEFINE_TYPE_WITH_CODE (TpTestsContactGroup, tp_tests_contact_group, - TP_TESTS_TYPE_CONTACT_LIST_BASE, - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, group_channel_iface_init)) - -static const gchar *contact_list_interfaces[] = { - TP_IFACE_CHANNEL_INTERFACE_GROUP, - NULL -}; - -enum -{ - PROP_OBJECT_PATH = 1, - PROP_CHANNEL_TYPE, - PROP_HANDLE_TYPE, - PROP_HANDLE, - PROP_TARGET_ID, - PROP_REQUESTED, - PROP_INITIATOR_HANDLE, - PROP_INITIATOR_ID, - PROP_CONNECTION, - PROP_MANAGER, - PROP_INTERFACES, - PROP_CHANNEL_DESTROYED, - PROP_CHANNEL_PROPERTIES, - N_PROPS -}; - -struct _TpTestsContactListBasePrivate -{ - TpBaseConnection *conn; - TpTestsContactListManager *manager; - gchar *object_path; - TpHandleType handle_type; - TpHandle handle; - - /* These are really booleans, but gboolean is signed. Thanks, GLib */ - unsigned closed:1; - unsigned disposed:1; -}; - -struct _TpTestsContactListPrivate -{ - int dummy:1; -}; - -struct _TpTestsContactGroupPrivate -{ - int dummy:1; -}; - -static void -tp_tests_contact_list_base_init (TpTestsContactListBase *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - TP_TESTS_TYPE_CONTACT_LIST_BASE, TpTestsContactListBasePrivate); -} - -static void -tp_tests_contact_list_init (TpTestsContactList *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TESTS_TYPE_CONTACT_LIST, - TpTestsContactListPrivate); -} - -static void -tp_tests_contact_group_init (TpTestsContactGroup *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TESTS_TYPE_CONTACT_GROUP, - TpTestsContactGroupPrivate); -} - -static void -constructed (GObject *object) -{ - TpTestsContactListBase *self = TP_TESTS_CONTACT_LIST_BASE (object); - void (*chain_up) (GObject *) = - ((GObjectClass *) tp_tests_contact_list_base_parent_class)->constructed; - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles - (self->priv->conn, TP_HANDLE_TYPE_CONTACT); - TpHandle self_handle = self->priv->conn->self_handle; - TpHandleRepoIface *handle_repo = tp_base_connection_get_handles - (self->priv->conn, self->priv->handle_type); - - if (chain_up != NULL) - chain_up (object); - - g_assert (TP_IS_BASE_CONNECTION (self->priv->conn)); - g_assert (TP_TESTS_IS_CONTACT_LIST_MANAGER (self->priv->manager)); - - tp_dbus_daemon_register_object ( - tp_base_connection_get_dbus_daemon (self->priv->conn), - self->priv->object_path, self); - - tp_handle_ref (handle_repo, self->priv->handle); - tp_group_mixin_init (object, G_STRUCT_OFFSET (TpTestsContactListBase, group), - contact_repo, self_handle); - /* Both the subclasses have full support for telepathy-spec 0.17.6. */ - tp_group_mixin_change_flags (object, - TP_CHANNEL_GROUP_FLAG_PROPERTIES, 0); -} - -static void -list_constructed (GObject *object) -{ - TpTestsContactList *self = TP_TESTS_CONTACT_LIST (object); - void (*chain_up) (GObject *) = - ((GObjectClass *) tp_tests_contact_list_parent_class)->constructed; - - if (chain_up != NULL) - chain_up (object); - - g_assert (self->parent.priv->handle_type == TP_HANDLE_TYPE_LIST); - - switch (self->parent.priv->handle) - { - case TP_TESTS_CONTACT_LIST_PUBLISH: - /* We can stop publishing presence to people, but we can't - * start sending people our presence unless they ask for it. - * - * (We can accept people's requests to see our presence - but that's - * always allowed, so there's no flag.) - */ - tp_group_mixin_change_flags (object, - TP_CHANNEL_GROUP_FLAG_CAN_REMOVE, 0); - break; - case TP_TESTS_CONTACT_LIST_STORED: - /* We can add people to our roster (not that that's very useful without - * also adding them to subscribe), and we can remove them altogether - * (which implicitly removes them from subscribe, publish, and all - * user-defined groups). - */ - tp_group_mixin_change_flags (object, - TP_CHANNEL_GROUP_FLAG_CAN_ADD | TP_CHANNEL_GROUP_FLAG_CAN_REMOVE, 0); - break; - case TP_TESTS_CONTACT_LIST_SUBSCRIBE: - /* We can ask people to show us their presence, attaching a message. - * We can also cancel (rescind) requests that they haven't replied to, - * and stop receiving their presence after they allow it. - */ - tp_group_mixin_change_flags (object, - TP_CHANNEL_GROUP_FLAG_CAN_ADD | TP_CHANNEL_GROUP_FLAG_MESSAGE_ADD | - TP_CHANNEL_GROUP_FLAG_CAN_REMOVE | - TP_CHANNEL_GROUP_FLAG_CAN_RESCIND, - 0); - break; - default: - g_assert_not_reached (); - } -} - -static void -group_constructed (GObject *object) -{ - TpTestsContactGroup *self = TP_TESTS_CONTACT_GROUP (object); - void (*chain_up) (GObject *) = - ((GObjectClass *) tp_tests_contact_group_parent_class)->constructed; - - if (chain_up != NULL) - chain_up (object); - - g_assert (self->parent.priv->handle_type == TP_HANDLE_TYPE_GROUP); - - /* We can add people to user-defined groups, and also remove them. */ - tp_group_mixin_change_flags (object, - TP_CHANNEL_GROUP_FLAG_CAN_ADD | TP_CHANNEL_GROUP_FLAG_CAN_REMOVE, 0); -} - - -static void -get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - TpTestsContactListBase *self = TP_TESTS_CONTACT_LIST_BASE (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_CONTACT_LIST); - break; - case PROP_HANDLE_TYPE: - g_value_set_uint (value, self->priv->handle_type); - break; - case PROP_HANDLE: - g_value_set_uint (value, self->priv->handle); - break; - case PROP_TARGET_ID: - { - TpHandleRepoIface *handle_repo = tp_base_connection_get_handles ( - self->priv->conn, self->priv->handle_type); - - g_value_set_string (value, - tp_handle_inspect (handle_repo, self->priv->handle)); - } - break; - case PROP_REQUESTED: - g_value_set_boolean (value, FALSE); - break; - case PROP_INITIATOR_HANDLE: - g_value_set_uint (value, 0); - break; - case PROP_INITIATOR_ID: - g_value_set_static_string (value, ""); - break; - case PROP_CONNECTION: - g_value_set_object (value, self->priv->conn); - break; - case PROP_MANAGER: - g_value_set_object (value, self->priv->manager); - break; - case PROP_INTERFACES: - g_value_set_boxed (value, contact_list_interfaces); - break; - case PROP_CHANNEL_DESTROYED: - g_value_set_boolean (value, self->priv->closed); - break; - case PROP_CHANNEL_PROPERTIES: - g_value_take_boxed (value, - tp_dbus_properties_mixin_make_properties_hash (object, - TP_IFACE_CHANNEL, "ChannelType", - TP_IFACE_CHANNEL, "TargetHandleType", - TP_IFACE_CHANNEL, "TargetHandle", - TP_IFACE_CHANNEL, "TargetID", - TP_IFACE_CHANNEL, "InitiatorHandle", - TP_IFACE_CHANNEL, "InitiatorID", - TP_IFACE_CHANNEL, "Requested", - TP_IFACE_CHANNEL, "Interfaces", - NULL)); - 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) -{ - TpTestsContactListBase *self = TP_TESTS_CONTACT_LIST_BASE (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 - * repository (or even type) yet - instead we ref it in the constructor. - */ - self->priv->handle = g_value_get_uint (value); - break; - case PROP_HANDLE_TYPE: - self->priv->handle_type = g_value_get_uint (value); - break; - case PROP_CHANNEL_TYPE: - /* this property is 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; - case PROP_MANAGER: - self->priv->manager = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -dispose (GObject *object) -{ - TpTestsContactListBase *self = TP_TESTS_CONTACT_LIST_BASE (object); - - if (self->priv->disposed) - return; - - self->priv->disposed = TRUE; - - if (!self->priv->closed) - { - self->priv->closed = TRUE; - tp_svc_channel_emit_closed (self); - } - - ((GObjectClass *) tp_tests_contact_list_base_parent_class)->dispose (object); -} - -static void -finalize (GObject *object) -{ - TpTestsContactListBase *self = TP_TESTS_CONTACT_LIST_BASE (object); - TpHandleRepoIface *handle_repo = tp_base_connection_get_handles - (self->priv->conn, self->priv->handle_type); - - tp_handle_unref (handle_repo, self->priv->handle); - g_free (self->priv->object_path); - tp_group_mixin_finalize (object); - - ((GObjectClass *) tp_tests_contact_list_base_parent_class)->finalize (object); -} - -static gboolean -group_add_member (GObject *object, - TpHandle handle, - const gchar *message, - GError **error) -{ - TpTestsContactListBase *self = TP_TESTS_CONTACT_LIST_BASE (object); - - return tp_tests_contact_list_manager_add_to_group (self->priv->manager, - object, self->priv->handle, handle, message, error); -} - -static gboolean -group_remove_member (GObject *object, - TpHandle handle, - const gchar *message, - GError **error) -{ - TpTestsContactListBase *self = TP_TESTS_CONTACT_LIST_BASE (object); - - return tp_tests_contact_list_manager_remove_from_group (self->priv->manager, - object, self->priv->handle, handle, message, error); -} - -static gboolean -list_add_member (GObject *object, - TpHandle handle, - const gchar *message, - GError **error) -{ - TpTestsContactListBase *self = TP_TESTS_CONTACT_LIST_BASE (object); - - return tp_tests_contact_list_manager_add_to_list (self->priv->manager, - object, self->priv->handle, handle, message, error); -} - -static gboolean -list_remove_member (GObject *object, - TpHandle handle, - const gchar *message, - GError **error) -{ - TpTestsContactListBase *self = TP_TESTS_CONTACT_LIST_BASE (object); - - return tp_tests_contact_list_manager_remove_from_list (self->priv->manager, - object, self->priv->handle, handle, message, error); -} - -static void -tp_tests_contact_list_base_class_init (TpTestsContactListBaseClass *klass) -{ - static TpDBusPropertiesMixinPropImpl channel_props[] = { - { "TargetHandleType", (gpointer) "handle-type", NULL }, - { "TargetHandle", (gpointer) "handle", NULL }, - { "ChannelType", (gpointer) "channel-type", NULL }, - { "Interfaces", (gpointer) "interfaces", NULL }, - { "TargetID", (gpointer) "target-id", NULL }, - { "Requested", (gpointer) "requested", NULL }, - { "InitiatorHandle", (gpointer) "initiator-handle", NULL }, - { "InitiatorID", (gpointer) "initiator-id", NULL }, - { NULL } - }; - static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { - { TP_IFACE_CHANNEL, - tp_dbus_properties_mixin_getter_gobject_properties, - NULL, - channel_props, - }, - { NULL } - }; - GObjectClass *object_class = (GObjectClass *) klass; - GParamSpec *param_spec; - - g_type_class_add_private (klass, sizeof (TpTestsContactListBasePrivate)); - - object_class->constructed = constructed; - 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"); - - g_object_class_override_property (object_class, PROP_CHANNEL_DESTROYED, - "channel-destroyed"); - g_object_class_override_property (object_class, PROP_CHANNEL_PROPERTIES, - "channel-properties"); - - 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_object ("manager", "TpTestsContactListManager", - "TpTestsContactListManager object that owns this channel", - TP_TESTS_TYPE_CONTACT_LIST_MANAGER, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_MANAGER, 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", "Chatroom's ID", - "The string obtained by inspecting the MUC's 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); - - klass->dbus_properties_class.interfaces = prop_interfaces; - tp_dbus_properties_mixin_class_init (object_class, - G_STRUCT_OFFSET (TpTestsContactListBaseClass, dbus_properties_class)); - - /* Group mixin is initialized separately for each subclass - they have - * different callbacks */ -} - -static void -tp_tests_contact_list_class_init (TpTestsContactListClass *klass) -{ - GObjectClass *object_class = (GObjectClass *) klass; - - g_type_class_add_private (klass, sizeof (TpTestsContactListPrivate)); - - object_class->constructed = list_constructed; - - tp_group_mixin_class_init (object_class, - G_STRUCT_OFFSET (TpTestsContactListBaseClass, group_class), - list_add_member, - list_remove_member); - tp_group_mixin_init_dbus_properties (object_class); -} - -static void -tp_tests_contact_group_class_init (TpTestsContactGroupClass *klass) -{ - GObjectClass *object_class = (GObjectClass *) klass; - - g_type_class_add_private (klass, sizeof (TpTestsContactGroupPrivate)); - - object_class->constructed = group_constructed; - - tp_group_mixin_class_init (object_class, - G_STRUCT_OFFSET (TpTestsContactListBaseClass, group_class), - group_add_member, - group_remove_member); - tp_group_mixin_init_dbus_properties (object_class); -} - -static void -list_channel_close (TpSvcChannel *iface G_GNUC_UNUSED, - DBusGMethodInvocation *context) -{ - GError e = { TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED, - (gchar *) "ContactList channels with handle type LIST may not be closed" }; - - dbus_g_method_return_error (context, &e); -} - -static void -group_channel_close (TpSvcChannel *iface, - DBusGMethodInvocation *context) -{ - TpTestsContactGroup *self = TP_TESTS_CONTACT_GROUP (iface); - TpTestsContactListBase *base = TP_TESTS_CONTACT_LIST_BASE (iface); - - if (tp_handle_set_size (base->group.members) > 0) - { - GError e = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE, - (gchar *) "Non-empty groups may not be deleted (closed)" }; - - dbus_g_method_return_error (context, &e); - return; - } - - if (!base->priv->closed) - { - /* If this was a real connection manager we'd delete the group here, - * if such a concept existed in the protocol (in XMPP, it doesn't). - * - * Afterwards, close the channel: - */ - base->priv->closed = TRUE; - tp_svc_channel_emit_closed (self); - } - - tp_svc_channel_return_from_close (context); -} - -static void -channel_get_channel_type (TpSvcChannel *iface G_GNUC_UNUSED, - DBusGMethodInvocation *context) -{ - tp_svc_channel_return_from_get_channel_type (context, - TP_IFACE_CHANNEL_TYPE_CONTACT_LIST); -} - -static void -channel_get_handle (TpSvcChannel *iface, - DBusGMethodInvocation *context) -{ - TpTestsContactListBase *self = TP_TESTS_CONTACT_LIST_BASE (iface); - - tp_svc_channel_return_from_get_handle (context, self->priv->handle_type, - self->priv->handle); -} - -static void -channel_get_interfaces (TpSvcChannel *iface G_GNUC_UNUSED, - DBusGMethodInvocation *context) -{ - tp_svc_channel_return_from_get_interfaces (context, - contact_list_interfaces); -} - -static void -channel_iface_init (gpointer iface, - gpointer data) -{ - TpSvcChannelClass *klass = iface; - -#define IMPLEMENT(x) tp_svc_channel_implement_##x (klass, channel_##x) - /* close is implemented in subclasses, so don't IMPLEMENT (close); */ - IMPLEMENT (get_channel_type); - IMPLEMENT (get_handle); - IMPLEMENT (get_interfaces); -#undef IMPLEMENT -} - -static void -list_channel_iface_init (gpointer iface, - gpointer data G_GNUC_UNUSED) -{ - TpSvcChannelClass *klass = iface; - -#define IMPLEMENT(x) tp_svc_channel_implement_##x (klass, list_channel_##x) - IMPLEMENT (close); -#undef IMPLEMENT -} - -static void -group_channel_iface_init (gpointer iface, - gpointer data G_GNUC_UNUSED) -{ - TpSvcChannelClass *klass = iface; - -#define IMPLEMENT(x) tp_svc_channel_implement_##x (klass, group_channel_##x) - IMPLEMENT (close); -#undef IMPLEMENT -} diff --git a/tests/lib/telepathy/contactlist/contact-list.h b/tests/lib/telepathy/contactlist/contact-list.h deleted file mode 100644 index 9d5535b..0000000 --- a/tests/lib/telepathy/contactlist/contact-list.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * TpTest ContactList channels with handle type LIST or GROUP - * - * Copyright © 2009 Collabora Ltd. - * Copyright © 2009 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_CONTACT_LIST_H -#define TP_TESTS_CONTACT_LIST_H - -#include - -#include -#include - -G_BEGIN_DECLS - -typedef struct _TpTestsContactListBase TpTestsContactListBase; -typedef struct _TpTestsContactListBaseClass TpTestsContactListBaseClass; -typedef struct _TpTestsContactListBasePrivate TpTestsContactListBasePrivate; - -typedef struct _TpTestsContactList TpTestsContactList; -typedef struct _TpTestsContactListClass TpTestsContactListClass; -typedef struct _TpTestsContactListPrivate TpTestsContactListPrivate; - -typedef struct _TpTestsContactGroup TpTestsContactGroup; -typedef struct _TpTestsContactGroupClass TpTestsContactGroupClass; -typedef struct _TpTestsContactGroupPrivate TpTestsContactGroupPrivate; - -GType tp_tests_contact_list_base_get_type (void); -GType tp_tests_contact_list_get_type (void); -GType tp_tests_contact_group_get_type (void); - -#define TP_TESTS_TYPE_CONTACT_LIST_BASE \ - (tp_tests_contact_list_base_get_type ()) -#define TP_TESTS_CONTACT_LIST_BASE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_CONTACT_LIST_BASE, \ - TpTestsContactListBase)) -#define TP_TESTS_CONTACT_LIST_BASE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_CONTACT_LIST_BASE, \ - TpTestsContactListBaseClass)) -#define TP_TESTS_IS_CONTACT_LIST_BASE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_CONTACT_LIST_BASE)) -#define TP_TESTS_IS_CONTACT_LIST_BASE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_CONTACT_LIST_BASE)) -#define TP_TESTS_CONTACT_LIST_BASE_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_CONTACT_LIST_BASE, \ - TpTestsContactListBaseClass)) - -#define TP_TESTS_TYPE_CONTACT_LIST \ - (tp_tests_contact_list_get_type ()) -#define TP_TESTS_CONTACT_LIST(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_CONTACT_LIST, \ - TpTestsContactList)) -#define TP_TESTS_CONTACT_LIST_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_CONTACT_LIST, \ - TpTestsContactListClass)) -#define TP_TESTS_IS_CONTACT_LIST(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_CONTACT_LIST)) -#define TP_TESTS_IS_CONTACT_LIST_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_CONTACT_LIST)) -#define TP_TESTS_CONTACT_LIST_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_CONTACT_LIST, \ - TpTestsContactListClass)) - -#define TP_TESTS_TYPE_CONTACT_GROUP \ - (tp_tests_contact_group_get_type ()) -#define TP_TESTS_CONTACT_GROUP(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_CONTACT_GROUP, \ - TpTestsContactGroup)) -#define TP_TESTS_CONTACT_GROUP_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_CONTACT_GROUP, \ - TpTestsContactGroupClass)) -#define TP_TESTS_IS_CONTACT_GROUP(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_CONTACT_GROUP)) -#define TP_TESTS_IS_CONTACT_GROUP_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_CONTACT_GROUP)) -#define TP_TESTS_CONTACT_GROUP_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_CONTACT_GROUP, \ - TpTestsContactGroupClass)) - -struct _TpTestsContactListBaseClass { - GObjectClass parent_class; - TpGroupMixinClass group_class; - TpDBusPropertiesMixinClass dbus_properties_class; -}; - -struct _TpTestsContactListClass { - TpTestsContactListBaseClass parent_class; -}; - -struct _TpTestsContactGroupClass { - TpTestsContactListBaseClass parent_class; -}; - -struct _TpTestsContactListBase { - GObject parent; - TpGroupMixin group; - TpTestsContactListBasePrivate *priv; -}; - -struct _TpTestsContactList { - TpTestsContactListBase parent; - TpTestsContactListPrivate *priv; -}; - -struct _TpTestsContactGroup { - TpTestsContactListBase parent; - TpTestsContactGroupPrivate *priv; -}; - -G_END_DECLS - -#endif 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. + * 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 + +#include +#include +#include +#include +#include +#include + +#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. + * 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 +#include +#include +#include + +#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. + * Copyright (C) 2007-2012 Collabora Ltd. * 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 #include #include #include +#include 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. + * 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 +#include + + +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. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +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. + * + * 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 + +#include +#include + +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. + * 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 + +#include + +#include +#include +#include +#include +#include +#include + +#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. + * 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 +#include + +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. + * 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 +#include +#include +#include +#include +#include +#include + +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. + * 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 +#include +#include +#include + +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 -#include +#include +#include #include -#include +#include #include -#include #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); -- 2.7.4