[folks] Implement ContactInfo in the Telepathy test backend.



commit 9000d07cfcc00dbbbc6e118fca34a19675756877
Author: Travis Reitter <travis reitter collabora co uk>
Date:   Thu Sep 29 14:44:35 2011 -0700

    Implement ContactInfo in the Telepathy test backend.
    
    Helps: bgo#657602 - Telepathy backend fails to set Personas' phone
    numbers from ContactInfo

 tests/lib/telepathy/contactlist/conn.c             |  234 +++++++++++++++++++-
 tests/lib/telepathy/contactlist/conn.h             |    1 +
 .../telepathy/contactlist/contact-list-manager.c   |   80 +++++++
 .../telepathy/contactlist/contact-list-manager.h   |    2 +
 tests/telepathy/individual-properties.vala         |    4 +
 5 files changed, 318 insertions(+), 3 deletions(-)
---
diff --git a/tests/lib/telepathy/contactlist/conn.c b/tests/lib/telepathy/contactlist/conn.c
index 748abef..cc35c4b 100644
--- a/tests/lib/telepathy/contactlist/conn.c
+++ b/tests/lib/telepathy/contactlist/conn.c
@@ -1,8 +1,8 @@
 /*
  * conn.c - an tp_test connection
  *
- * Copyright  2007-2009 Collabora Ltd. <http://www.collabora.co.uk/>
- * Copyright  2007-2009 Nokia Corporation
+ * Copyright  2007-2011 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright  2007-2010 Nokia Corporation
  *
  * Copying and distribution of this file, with or without modification,
  * are permitted in any medium without royalty provided the copyright
@@ -22,6 +22,7 @@
 #include "contact-list-manager.h"
 
 static void init_aliasing (gpointer, gpointer);
+static void init_contact_info (gpointer, gpointer);
 
 G_DEFINE_TYPE_WITH_CODE (TpTestContactListConnection,
     tp_test_contact_list_connection,
@@ -33,7 +34,9 @@ G_DEFINE_TYPE_WITH_CODE (TpTestContactListConnection,
     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))
+      tp_presence_mixin_simple_presence_iface_init);
+    G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_INFO,
+      init_contact_info))
 
 enum
 {
@@ -245,6 +248,21 @@ alias_updated_cb (TpTestContactListManager *manager,
 }
 
 static void
+contact_info_updated_cb (TpTestContactListManager *manager,
+                         TpHandle contact,
+                         TpTestContactListConnection *self)
+{
+  GPtrArray *contact_info = tp_test_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 (TpTestContactListManager *manager,
                      TpHandle contact,
                      TpTestContactListConnection *self)
@@ -280,6 +298,8 @@ create_channel_managers (TpBaseConnection *conn)
 
   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);
 
@@ -343,6 +363,69 @@ aliasing_fill_contact_attributes (GObject *object,
 }
 
 static void
+contact_info_fill_contact_attributes (GObject *object,
+                                      const GArray *contacts,
+                                      GHashTable *attributes_hash)
+{
+  TpTestContactListConnection *self = TP_TEST_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_test_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, "tel",
+              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);
@@ -358,6 +441,9 @@ constructed (GObject *object)
   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 (TpTestContactListConnection, presence_mixin));
@@ -457,11 +543,21 @@ tp_test_contact_list_connection_class_init (
 {
   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;
@@ -520,6 +616,10 @@ tp_test_contact_list_connection_class_init (
       status_available, get_contact_statuses, set_own_status,
       tp_test_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 (TpTestContactListConnectionClass, properties_class));
 }
 
 static void
@@ -669,6 +769,134 @@ init_aliasing (gpointer iface,
 #undef IMPLEMENT
 }
 
+static void
+get_contact_info (
+    TpSvcConnectionInterfaceContactInfo *iface,
+    const GArray *contacts,
+    DBusGMethodInvocation *context)
+{
+  TpTestContactListConnection *self = TP_TEST_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_test_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)
+{
+  TpTestContactListConnection *self = TP_TEST_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_test_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 (TpTestContactListConnection *self,
+                                   guint contact,
+                                   DBusGMethodInvocation *context)
+{
+  GError *error = NULL;
+  GPtrArray *contact_info;
+
+  contact_info = tp_test_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)
+{
+  TpTestContactListConnection *self = TP_TEST_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
+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);
+#undef IMPLEMENT
+}
+
 TpTestContactListConnection *
 tp_test_contact_list_connection_new (const gchar *account,
     const gchar *protocol,
diff --git a/tests/lib/telepathy/contactlist/conn.h b/tests/lib/telepathy/contactlist/conn.h
index c174d0a..e606603 100644
--- a/tests/lib/telepathy/contactlist/conn.h
+++ b/tests/lib/telepathy/contactlist/conn.h
@@ -29,6 +29,7 @@ typedef struct _TpTestContactListConnectionPrivate
 
 struct _TpTestContactListConnectionClass {
     TpBaseConnectionClass parent_class;
+    TpDBusPropertiesMixinClass properties_class;
     TpPresenceMixinClass presence_mixin;
     TpContactsMixinClass contacts_mixin;
 };
diff --git a/tests/lib/telepathy/contactlist/contact-list-manager.c b/tests/lib/telepathy/contactlist/contact-list-manager.c
index 92f4367..e979f8e 100644
--- a/tests/lib/telepathy/contactlist/contact-list-manager.c
+++ b/tests/lib/telepathy/contactlist/contact-list-manager.c
@@ -62,6 +62,7 @@ typedef struct {
 
     TpHandleSet *tags;
 
+    GPtrArray *contact_info;
 } TpTestContactDetails;
 
 static TpTestContactDetails *
@@ -78,6 +79,9 @@ tp_test_contact_details_destroy (gpointer p)
   if (d->tags != NULL)
     tp_handle_set_destroy (d->tags);
 
+  if (d->contact_info != NULL)
+    g_ptr_array_unref (d->contact_info);
+
   g_free (d->id);
   g_free (d->alias);
   g_slice_free (TpTestContactDetails, d);
@@ -95,6 +99,7 @@ enum
 {
   ALIAS_UPDATED,
   PRESENCE_UPDATED,
+  CONTACT_INFO_UPDATED,
   N_SIGNALS
 };
 
@@ -374,6 +379,38 @@ static TpTestContactGroup *ensure_group (TpTestContactListManager *self,
 static TpTestContactList *ensure_list (TpTestContactListManager *self,
     TpTestContactListHandle 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_free (field_name_down);
+}
+
 static gboolean
 receive_contact_lists (gpointer p)
 {
@@ -432,6 +469,13 @@ receive_contact_lists (gpointer p)
   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";
@@ -466,6 +510,18 @@ receive_contact_lists (gpointer p)
   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[] = { "Olivier Crete", NULL };
+    _insert_contact_field (d->contact_info, "fn", NULL,
+        (const gchar * const *) values);
+  }
   tp_handle_unref (self->priv->contact_repo, handle);
 
   id = "travis example com";
@@ -496,6 +552,7 @@ receive_contact_lists (gpointer p)
     {
       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_intset_destroy (set);
@@ -548,6 +605,7 @@ receive_contact_lists (gpointer p)
     {
       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_intset_destroy (set);
@@ -576,6 +634,7 @@ receive_contact_lists (gpointer p)
   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);
@@ -598,6 +657,7 @@ receive_contact_lists (gpointer p)
   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,
@@ -724,6 +784,13 @@ tp_test_contact_list_manager_class_init (TpTestContactListManagerClass *klass)
       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);
 }
 
 static void
@@ -1076,6 +1143,7 @@ send_updated_roster (TpTestContactListManager *self,
        * 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);
 
       tp_handle_unref (self->priv->contact_repo, handle);
     }
@@ -1683,3 +1751,15 @@ tp_test_contact_list_manager_set_alias (TpTestContactListManager *self,
       TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
   tp_intset_destroy (set);
 }
+
+GPtrArray *
+tp_test_contact_list_manager_get_contact_info (TpTestContactListManager *self,
+                                               TpHandle contact)
+{
+  TpTestContactDetails *d = lookup_contact (self, contact);
+
+  if (d != NULL)
+    return d->contact_info;
+
+  return NULL;
+}
diff --git a/tests/lib/telepathy/contactlist/contact-list-manager.h b/tests/lib/telepathy/contactlist/contact-list-manager.h
index 586e3f6..797f3fb 100644
--- a/tests/lib/telepathy/contactlist/contact-list-manager.h
+++ b/tests/lib/telepathy/contactlist/contact-list-manager.h
@@ -102,6 +102,8 @@ const gchar *tp_test_contact_list_manager_get_alias (
     TpTestContactListManager *self, TpHandle contact);
 void tp_test_contact_list_manager_set_alias (
     TpTestContactListManager *self, TpHandle contact, const gchar *alias);
+GPtrArray * tp_test_contact_list_manager_get_contact_info (
+    TpTestContactListManager *self, TpHandle contact);
 
 G_END_DECLS
 
diff --git a/tests/telepathy/individual-properties.vala b/tests/telepathy/individual-properties.vala
index c5f222f..ae8e84c 100644
--- a/tests/telepathy/individual-properties.vala
+++ b/tests/telepathy/individual-properties.vala
@@ -93,6 +93,10 @@ public class IndividualPropertiesTests : Folks.TestCase
               assert (i.groups.size == 2);
               assert (i.groups.contains ("Montreal") == true);
               assert (i.groups.contains ("Francophones") == true);
+
+              /* Check ContactInfo-provided properties */
+              assert (new PhoneFieldDetails ("+15142345678")
+                  in i.phone_numbers);
             }
 
           assert (removed.size == 1);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]