[Telepathy-commits] [telepathy-gabble/master] use presence interfaces to announce view buddies as online (first naive implementation)

Guillaume Desmottes guillaume.desmottes at collabora.co.uk
Wed Oct 15 08:45:06 PDT 2008


---
 src/olpc-view.c                     |   25 +++++++-
 src/presence-cache.c                |   87 ++++++++++++++++++++++++
 src/presence-cache.h                |    6 ++
 src/presence.h                      |    1 +
 tests/twisted/Makefile.am           |    1 +
 tests/twisted/olpc/view-presence.py |  124 +++++++++++++++++++++++++++++++++++
 6 files changed, 242 insertions(+), 2 deletions(-)
 create mode 100644 tests/twisted/olpc/view-presence.py

diff --git a/src/olpc-view.c b/src/olpc-view.c
index b33b6ab..fc83f0c 100644
--- a/src/olpc-view.c
+++ b/src/olpc-view.c
@@ -40,6 +40,7 @@
 #include "gabble-signals-marshal.h"
 #include "olpc-activity.h"
 #include "namespaces.h"
+#include "presence-cache.h"
 #include "util.h"
 
 /* signals */
@@ -644,8 +645,9 @@ gabble_olpc_view_add_buddies (GabbleOlpcView *self,
   GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
   guint i;
   GArray *empty;
-  TpHandleRepoIface *room_repo;
+  TpHandleRepoIface *room_repo, *contact_repo;
   GArray *buddies_changed;
+  TpHandleSet *buddies_added;
 
   g_assert (buddies->len == buddies_properties->len);
   if (buddies->len == 0)
@@ -653,9 +655,12 @@ gabble_olpc_view_add_buddies (GabbleOlpcView *self,
 
   room_repo = tp_base_connection_get_handles ((TpBaseConnection *) self->conn,
       TP_HANDLE_TYPE_ROOM);
+  contact_repo = tp_base_connection_get_handles (
+      (TpBaseConnection *) self->conn, TP_HANDLE_TYPE_CONTACT);
 
   empty = g_array_new (FALSE, FALSE, sizeof (TpHandle));
   buddies_changed = g_array_new (FALSE, FALSE, sizeof (TpHandle));
+  buddies_added = tp_handle_set_new (contact_repo);
 
   /* store properties */
   for (i = 0; i < buddies->len; i++)
@@ -666,7 +671,13 @@ gabble_olpc_view_add_buddies (GabbleOlpcView *self,
       handle = g_array_index (buddies, TpHandle, i);
       properties = g_ptr_array_index (buddies_properties, i);
 
-      tp_handle_set_add (priv->buddies, handle);
+      if (!tp_handle_set_is_member (priv->buddies, handle))
+          {
+            tp_handle_set_add (priv->buddies, handle);
+
+            tp_handle_set_add (buddies_added, handle);
+           }
+
       g_hash_table_insert (priv->buddy_properties, GUINT_TO_POINTER (handle),
           properties);
       g_hash_table_ref (properties);
@@ -699,6 +710,13 @@ gabble_olpc_view_add_buddies (GabbleOlpcView *self,
         }
     }
 
+  if (tp_handle_set_size (buddies_added) > 0)
+    {
+      gabble_presence_cache_contacts_added_to_olpc_view (
+          self->conn->presence_cache, buddies_added);
+    }
+  tp_handle_set_destroy (buddies_added);
+
   gabble_svc_olpc_channel_interface_view_emit_buddies_changed (self, buddies,
       empty);
 
@@ -745,6 +763,9 @@ gabble_olpc_view_remove_buddies (GabbleOlpcView *self,
   gabble_svc_olpc_channel_interface_view_emit_buddies_changed (self, empty,
       removed);
 
+  gabble_presence_cache_contacts_removed_from_olpc_view (
+      self->conn->presence_cache, buddies);
+
   g_array_free (empty, TRUE);
   g_array_free (removed, TRUE);
 }
diff --git a/src/presence-cache.c b/src/presence-cache.c
index 2a06562..9baa61e 100644
--- a/src/presence-cache.c
+++ b/src/presence-cache.c
@@ -1473,3 +1473,90 @@ gabble_presence_cache_really_remove (
   tp_handle_set_remove (priv->presence_handles, handle);
 }
 
+void
+gabble_presence_cache_contacts_added_to_olpc_view (GabblePresenceCache *self,
+                                                   TpHandleSet *handles)
+{
+  GArray *tmp, *changed;
+  guint i;
+
+  tmp = tp_handle_set_to_array (handles);
+
+  changed = g_array_new (FALSE, FALSE, sizeof (TpHandle));
+
+  for (i = 0; i < tmp->len; i++)
+    {
+      TpHandle handle;
+      GabblePresence *presence;
+
+      handle = g_array_index (tmp, TpHandle, i);
+
+      presence = gabble_presence_cache_get (self, handle);
+      if (presence == NULL)
+        {
+          presence = _cache_insert (self, handle);
+        }
+
+      presence->olpc_views++;
+
+      if (presence->status <= GABBLE_PRESENCE_HIDDEN)
+        {
+          presence->status = GABBLE_PRESENCE_AVAILABLE;
+          g_array_append_val (changed, handle);
+        }
+    }
+
+  if (changed->len > 0)
+    {
+      g_signal_emit (self, signals[PRESENCES_UPDATED], 0, changed);
+    }
+
+  g_array_free (tmp, TRUE);
+  g_array_free (changed, TRUE);
+}
+
+void
+gabble_presence_cache_contacts_removed_from_olpc_view (
+    GabblePresenceCache *self,
+    TpHandleSet *handles)
+{
+  GArray *tmp, *changed;
+  guint i;
+
+  tmp = tp_handle_set_to_array (handles);
+
+  changed = g_array_new (FALSE, FALSE, sizeof (TpHandle));
+
+  for (i = 0; i < tmp->len; i++)
+    {
+      TpHandle handle;
+      GabblePresence *presence;
+
+      handle = g_array_index (tmp, TpHandle, i);
+
+      presence = gabble_presence_cache_get (self, handle);
+      if (presence == NULL)
+        {
+          presence = _cache_insert (self, handle);
+        }
+
+      presence->olpc_views--;
+
+      if (presence->olpc_views == 0)
+        {
+          presence->status = GABBLE_PRESENCE_OFFLINE;
+          /* FIXME: don't do that if we have a presence */
+          /* FIXME: set OFFLINE or unknown depending the roster status */
+          g_array_append_val (changed, handle);
+        }
+    }
+
+  if (changed->len > 0)
+    {
+      g_signal_emit (self, signals[PRESENCES_UPDATED], 0, changed);
+    }
+
+  g_array_free (tmp, TRUE);
+  g_array_free (changed, TRUE);
+
+}
diff --git a/src/presence-cache.h b/src/presence-cache.h
index fc18d54..9c0cd1e 100644
--- a/src/presence-cache.h
+++ b/src/presence-cache.h
@@ -85,6 +85,12 @@ void gabble_presence_cache_add_bundle_caps (GabblePresenceCache *cache,
 void gabble_presence_cache_really_remove (GabblePresenceCache *cache,
     TpHandle handle);
 
+void gabble_presence_cache_contacts_added_to_olpc_view (
+    GabblePresenceCache *cache, TpHandleSet *handles);
+
+void gabble_presence_cache_contacts_removed_from_olpc_view (
+    GabblePresenceCache *cache, TpHandleSet *handles);
+
 G_END_DECLS
 
 #endif /* __GABBLE_PRESENCE_CACHE_H__ */
diff --git a/src/presence.h b/src/presence.h
index 5663a19..e39e6ef 100644
--- a/src/presence.h
+++ b/src/presence.h
@@ -62,6 +62,7 @@ struct _GabblePresence {
     gchar *avatar_sha1;
     gboolean keep_unavailable;
     GabblePresencePrivate *priv;
+    guint olpc_views;
 };
 
 typedef struct _GabblePresenceClass GabblePresenceClass;
diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am
index 90ef4e6..c5aa679 100644
--- a/tests/twisted/Makefile.am
+++ b/tests/twisted/Makefile.am
@@ -17,6 +17,7 @@ TWISTED_TESTS = \
 	olpc/gadget-invite.py \
 	olpc/gadget-publish.py \
 	olpc/gadget-restarted.py \
+	olpc/view-presence.py \
 	presence/presence.py \
 	roster/ensure.py \
 	roster/groups.py \
diff --git a/tests/twisted/olpc/view-presence.py b/tests/twisted/olpc/view-presence.py
new file mode 100644
index 0000000..d10c4c8
--- /dev/null
+++ b/tests/twisted/olpc/view-presence.py
@@ -0,0 +1,124 @@
+"""
+test contact presence from views
+"""
+
+import dbus
+
+from servicetest import call_async, EventPattern
+from gabbletest import exec_test, make_result_iq, acknowledge_iq, sync_stream
+
+from twisted.words.xish import domish, xpath
+from twisted.words.protocols.jabber.client import IQ
+
+from util import (announce_gadget, properties_to_xml, parse_properties,
+    create_gadget_message, close_view)
+
+NS_OLPC_BUDDY_PROPS = "http://laptop.org/xmpp/buddy-properties"
+NS_OLPC_ACTIVITIES = "http://laptop.org/xmpp/activities"
+NS_OLPC_CURRENT_ACTIVITY = "http://laptop.org/xmpp/current-activity"
+NS_OLPC_ACTIVITY_PROPS = "http://laptop.org/xmpp/activity-properties"
+NS_OLPC_BUDDY = "http://laptop.org/xmpp/buddy"
+NS_OLPC_ACTIVITY = "http://laptop.org/xmpp/activity"
+
+NS_PUBSUB = "http://jabber.org/protocol/pubsub"
+NS_DISCO_INFO = "http://jabber.org/protocol/disco#info"
+NS_DISCO_ITEMS = "http://jabber.org/protocol/disco#items"
+
+NS_AMP = "http://jabber.org/protocol/amp"
+
+tp_name_prefix = 'org.freedesktop.Telepathy'
+olpc_name_prefix = 'org.laptop.Telepathy'
+
+def test(q, bus, conn, stream):
+    conn.Connect()
+
+    _, iq_event, disco_event = q.expect_many(
+        EventPattern('dbus-signal', signal='StatusChanged', args=[0, 1]),
+        EventPattern('stream-iq', to=None, query_ns='vcard-temp',
+            query_name='vCard'),
+        EventPattern('stream-iq', to='localhost', query_ns=NS_DISCO_ITEMS))
+
+    acknowledge_iq(stream, iq_event.stanza)
+
+    buddy_info_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo')
+    gadget_iface = dbus.Interface(conn, 'org.laptop.Telepathy.Gadget')
+    requests_iface = dbus.Interface(conn, tp_name_prefix + '.Connection.Interface.Requests')
+
+    announce_gadget(q, stream, disco_event.stanza)
+    sync_stream(q, stream)
+
+    # request 3 random buddies
+    call_async(q, requests_iface, 'CreateChannel',
+        { tp_name_prefix + '.Channel.ChannelType':
+            olpc_name_prefix + '.Channel.Type.BuddyView',
+          olpc_name_prefix + '.Channel.Interface.View.MaxSize': 3
+          })
+
+    iq_event, return_event, new_channels_event, new_channel_event = q.expect_many(
+        EventPattern('stream-iq', to='gadget.localhost',
+            query_ns=NS_OLPC_BUDDY),
+        EventPattern('dbus-return', method='CreateChannel'),
+        EventPattern('dbus-signal', signal='NewChannels'),
+        EventPattern('dbus-signal', signal='NewChannel'))
+
+    view = iq_event.stanza.firstChildElement()
+    assert view.name == 'view'
+    assert view['id'] == '1'
+    assert view['size'] == '3'
+
+    # reply to random query
+    reply = make_result_iq(stream, iq_event.stanza)
+    reply['from'] = 'gadget.localhost'
+    reply['to'] = 'alice at localhost'
+    view = xpath.queryForNodes('/iq/view', reply)[0]
+    buddy = view.addElement((None, "buddy"))
+    buddy['jid'] = 'charles at localhost'
+    buddy = view.addElement((None, "buddy"))
+    buddy['jid'] = 'bob at localhost'
+    stream.send(reply)
+
+    view_path = return_event.value[0]
+    props = return_event.value[1]
+    view1 = bus.get_object(conn.bus_name, view_path)
+
+    event, _ = q.expect_many(
+        EventPattern('dbus-signal', signal='PresencesChanged'),
+        EventPattern('dbus-signal', signal='PresenceUpdate'))
+
+    handles = {}
+    handles['bob'], handles['charles'] = conn.RequestHandles(1, ['bob at localhost', 'charles at localhost'])
+
+    presence = event.args[0]
+    # Connection_Presence_Type_Available = 2
+    assert presence[handles['bob']] == (2, 'available', '')
+    assert presence[handles['charles']] == (2, 'available', '')
+
+    event = q.expect('dbus-signal', signal='BuddiesChanged')
+    added, removed = event.args
+    assert removed == []
+    assert len(added) == 2
+    assert sorted(conn.InspectHandles(1, added)) == ['bob at localhost',
+            'charles at localhost']
+
+    # remove bob from view
+    message = create_gadget_message("test at localhost")
+
+    added = message.addElement((NS_OLPC_BUDDY, 'removed'))
+    added['id'] = '1'
+    buddy = added.addElement((None, 'buddy'))
+    buddy['jid'] = 'bob at localhost'
+
+    stream.send(message)
+
+    event = q.expect('dbus-signal', signal='BuddiesChanged')
+
+    event, _ = q.expect_many(
+        EventPattern('dbus-signal', signal='PresencesChanged'),
+        EventPattern('dbus-signal', signal='PresenceUpdate'))
+
+    presence = event.args[0]
+    # Connection_Presence_Type_Offline = 1
+    assert presence[handles['bob']] == (1, 'offline', '')
+
+if __name__ == '__main__':
+    exec_test(test)
-- 
1.5.6.5




More information about the Telepathy-commits mailing list