summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonny Lamb <jonny.lamb@collabora.co.uk>2011-08-31 08:58:55 +0100
committerJonny Lamb <jonny.lamb@collabora.co.uk>2011-09-01 13:26:37 +0100
commitd887fdc2d23bf00322c9923e8eead7c5f0607302 (patch)
treec546b36d7d3c6d870f71d1ff31a720a43bd63495
parent5dcf95eaf432b5af1edf82e87f40f795a3265a35 (diff)
presence: start holding a list of data forms
Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
-rw-r--r--src/caps-hash.c5
-rw-r--r--src/connection.c21
-rw-r--r--src/presence-cache.c13
-rw-r--r--src/presence.c35
-rw-r--r--src/presence.h2
-rw-r--r--tests/test-presence.c6
6 files changed, 74 insertions, 8 deletions
diff --git a/src/caps-hash.c b/src/caps-hash.c
index bf8a2a08..c2bbb598 100644
--- a/src/caps-hash.c
+++ b/src/caps-hash.c
@@ -61,6 +61,7 @@ caps_hash_compute_from_self_presence (GabbleConnection *self)
const GabbleCapabilitySet *cap_set;
GPtrArray *features = g_ptr_array_new ();
GPtrArray *identities = wocky_disco_identity_array_new ();
+ GPtrArray *data_forms;
gchar *str;
/* XEP-0030 requires at least 1 identity. We don't need more. */
@@ -71,7 +72,9 @@ caps_hash_compute_from_self_presence (GabbleConnection *self)
cap_set = gabble_presence_peek_caps (presence);
gabble_capability_set_foreach (cap_set, ptr_array_add_str, features);
- str = wocky_caps_hash_compute_from_lists (features, identities, NULL);
+ data_forms = gabble_presence_peek_data_forms (presence);
+
+ str = wocky_caps_hash_compute_from_lists (features, identities, data_forms);
g_ptr_array_free (features, TRUE);
wocky_disco_identity_array_free (identities);
diff --git a/src/connection.c b/src/connection.c
index 791b9416..f82846b5 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -452,7 +452,7 @@ gabble_connection_constructor (GType type,
g_free, (GDestroyNotify) gabble_capability_set_free);
priv->client_data_forms = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify) g_object_unref);
+ g_free, (GDestroyNotify) g_ptr_array_unref);
/* Historically, the optional Jingle transports were in our initial
* presence, but could be removed by AdvertiseCapabilities(). Emulate
@@ -2411,10 +2411,13 @@ gabble_connection_refresh_capabilities (GabbleConnection *self,
GHashTableIter iter;
gpointer k, v;
GabbleCapabilitySet *save_set;
+ GPtrArray *data_forms;
save_set = self->priv->all_caps;
self->priv->all_caps = gabble_capability_set_new ();
+ data_forms = g_ptr_array_new ();
+
gabble_capability_set_update (self->priv->all_caps,
gabble_capabilities_get_fixed_caps ());
gabble_capability_set_update (self->priv->all_caps, self->priv->notify_caps);
@@ -2422,6 +2425,7 @@ gabble_connection_refresh_capabilities (GabbleConnection *self,
gabble_capability_set_update (self->priv->all_caps, self->priv->sidecar_caps);
gabble_capability_set_update (self->priv->all_caps, self->priv->bonus_caps);
+ /* first, normal caps */
g_hash_table_iter_init (&iter, self->priv->client_caps);
while (g_hash_table_iter_next (&iter, &k, &v))
@@ -2437,13 +2441,22 @@ gabble_connection_refresh_capabilities (GabbleConnection *self,
gabble_capability_set_update (self->priv->all_caps, v);
}
+ /* now data forms */
+ g_hash_table_iter_init (&iter, self->priv->client_data_forms);
+
+ /* just borrow the ref, data_forms doesn't have a free func */
+ while (g_hash_table_iter_next (&iter, &k, &v))
+ tp_g_ptr_array_extend (data_forms, v);
+
if (self->self_presence != NULL)
gabble_presence_set_capabilities (self->self_presence,
- self->priv->resource, self->priv->all_caps, self->priv->caps_serial++);
+ self->priv->resource, self->priv->all_caps, data_forms,
+ self->priv->caps_serial++);
if (gabble_capability_set_equals (self->priv->all_caps, save_set))
{
gabble_capability_set_free (save_set);
+ g_ptr_array_unref (data_forms);
DEBUG ("nothing to do");
return FALSE;
}
@@ -2452,6 +2465,7 @@ gabble_connection_refresh_capabilities (GabbleConnection *self,
if (base->status != TP_CONNECTION_STATUS_CONNECTED)
{
gabble_capability_set_free (save_set);
+ g_ptr_array_unref (data_forms);
DEBUG ("not emitting self-presence stanza: not connected yet");
return FALSE;
}
@@ -2459,6 +2473,7 @@ gabble_connection_refresh_capabilities (GabbleConnection *self,
if (!conn_presence_signal_own_presence (self, NULL, &error))
{
gabble_capability_set_free (save_set);
+ g_ptr_array_unref (data_forms);
DEBUG ("error sending presence: %s", error->message);
g_error_free (error);
return FALSE;
@@ -2469,6 +2484,8 @@ gabble_connection_refresh_capabilities (GabbleConnection *self,
else
*old_out = save_set;
+ g_ptr_array_unref (data_forms);
+
return TRUE;
}
diff --git a/src/presence-cache.c b/src/presence-cache.c
index 05556f8b..c70d86e0 100644
--- a/src/presence-cache.c
+++ b/src/presence-cache.c
@@ -1007,13 +1007,15 @@ _parse_node (GabblePresence *presence,
if (!tp_strdiff (node, "http://mail.google.com/xmpp/client/caps"))
{
GabbleCapabilitySet *cap_set = gabble_capability_set_new ();
+ GPtrArray *tmp = g_ptr_array_new ();
DEBUG ("Client is Google Web Client");
gabble_capability_set_add (cap_set, QUIRK_GOOGLE_WEBMAIL_CLIENT);
gabble_capability_set_add (cap_set, QUIRK_OMITS_CONTENT_CREATORS);
- gabble_presence_set_capabilities (presence, resource, cap_set, serial);
+ gabble_presence_set_capabilities (presence, resource, cap_set, tmp, serial); /* TODO */
gabble_capability_set_free (cap_set);
+ g_ptr_array_unref (tmp);
}
}
@@ -1148,6 +1150,7 @@ set_caps_for (DiscoWaiter *waiter,
GabblePresence *presence = gabble_presence_cache_get (cache, waiter->handle);
GabbleCapabilitySet *old_cap_set;
const GabbleCapabilitySet *new_cap_set;
+ GPtrArray *tmp = g_ptr_array_new ();
if (presence == NULL)
return;
@@ -1158,10 +1161,11 @@ set_caps_for (DiscoWaiter *waiter,
waiter->handle, responder_handle, responder_jid);
gabble_presence_set_capabilities (presence, waiter->resource, cap_set,
- waiter->serial);
+ tmp, waiter->serial); /* TODO */
new_cap_set = gabble_presence_peek_caps (presence);
emit_capabilities_update (cache, waiter->handle, old_cap_set, new_cap_set);
gabble_capability_set_free (old_cap_set);
+ g_ptr_array_unref (tmp);
if (gabble_presence_update_client_types (presence, waiter->resource,
client_types))
@@ -1499,9 +1503,12 @@ _process_caps_uri (GabblePresenceCache *cache,
if (presence)
{
guint types;
+ GPtrArray *tmp = g_ptr_array_new ();
gabble_presence_set_capabilities (
- presence, resource, cap_set, serial);
+ presence, resource, cap_set, tmp, serial);
+
+ g_ptr_array_unref (tmp);
/* We can only get this information from actual disco replies,
* so we depend on having this information from the caps cache. */
diff --git a/src/presence.c b/src/presence.c
index a707822a..aa156342 100644
--- a/src/presence.c
+++ b/src/presence.c
@@ -44,6 +44,7 @@ struct _Resource {
gchar *name;
guint client_type;
GabbleCapabilitySet *cap_set;
+ GPtrArray *data_forms;
guint caps_serial;
GabblePresenceId status;
gchar *status_message;
@@ -58,6 +59,9 @@ struct _GabblePresencePrivate {
/* The aggregated caps of all the contacts' resources. */
GabbleCapabilitySet *cap_set;
+ /* The aggregated data forms of all the contacts' resources */
+ GPtrArray *data_forms;
+
gchar *no_resource_status_message;
GSList *resources;
guint olpc_views;
@@ -72,6 +76,8 @@ _resource_new (gchar *name)
new->name = name;
new->client_type = 0;
new->cap_set = gabble_capability_set_new ();
+ new->data_forms = g_ptr_array_new_with_free_func (
+ (GDestroyNotify) g_object_unref);
new->status = GABBLE_PRESENCE_OFFLINE;
new->status_message = NULL;
new->priority = 0;
@@ -87,6 +93,7 @@ _resource_free (Resource *resource)
g_free (resource->name);
g_free (resource->status_message);
gabble_capability_set_free (resource->cap_set);
+ g_ptr_array_unref (resource->data_forms);
g_slice_free (Resource, resource);
}
@@ -103,6 +110,7 @@ gabble_presence_finalize (GObject *object)
g_slist_free (priv->resources);
gabble_capability_set_free (priv->cap_set);
+ g_ptr_array_unref (priv->data_forms);
g_free (presence->nickname);
g_free (presence->avatar_sha1);
@@ -128,6 +136,8 @@ gabble_presence_init (GabblePresence *self)
priv = self->priv;
priv->cap_set = gabble_capability_set_new ();
+ priv->data_forms = g_ptr_array_new_with_free_func (
+ (GDestroyNotify) g_object_unref);
priv->resources = NULL;
self->status = GABBLE_PRESENCE_UNKNOWN;
@@ -198,6 +208,13 @@ gabble_presence_peek_caps (GabblePresence *presence)
return presence->priv->cap_set;
}
+GPtrArray *
+gabble_presence_peek_data_forms (GabblePresence *presence)
+{
+ g_return_val_if_fail (presence != NULL, NULL);
+ return presence->priv->data_forms;
+}
+
gboolean
gabble_presence_has_resources (GabblePresence *self)
{
@@ -266,10 +283,19 @@ gabble_presence_resource_has_caps (GabblePresence *presence,
return FALSE;
}
+static void
+extend_and_dup (GPtrArray *target,
+ GPtrArray *source)
+{
+ g_ptr_array_foreach (source, (GFunc) g_object_ref, NULL);
+ tp_g_ptr_array_extend (target, source);
+}
+
void
gabble_presence_set_capabilities (GabblePresence *presence,
const gchar *resource,
const GabbleCapabilitySet *cap_set,
+ const GPtrArray *data_forms,
guint serial)
{
GabblePresencePrivate *priv = presence->priv;
@@ -288,11 +314,13 @@ gabble_presence_set_capabilities (GabblePresence *presence,
}
gabble_capability_set_clear (priv->cap_set);
+ g_ptr_array_set_size (priv->data_forms, 0);
if (resource == NULL)
{
DEBUG ("Setting capabilities for bare JID");
gabble_capability_set_update (priv->cap_set, cap_set);
+ extend_and_dup (priv->data_forms, (GPtrArray *) data_forms);
return;
}
@@ -315,6 +343,7 @@ gabble_presence_set_capabilities (GabblePresence *presence,
tmp->caps_serial);
tmp->caps_serial = serial;
gabble_capability_set_clear (tmp->cap_set);
+ g_ptr_array_set_size (tmp->data_forms, 0);
}
if (serial >= tmp->caps_serial)
@@ -322,10 +351,16 @@ gabble_presence_set_capabilities (GabblePresence *presence,
DEBUG ("updating caps for resource %s", resource);
gabble_capability_set_update (tmp->cap_set, cap_set);
+
+ /* TODO: deal with duplicates */
+ extend_and_dup (tmp->data_forms, (GPtrArray *) data_forms);
}
}
gabble_capability_set_update (priv->cap_set, tmp->cap_set);
+
+ /* TODO: deal with duplicates */
+ extend_and_dup (priv->data_forms, tmp->data_forms);
}
}
diff --git a/src/presence.h b/src/presence.h
index 4f9126d0..5406bd84 100644
--- a/src/presence.h
+++ b/src/presence.h
@@ -96,11 +96,13 @@ gboolean gabble_presence_update (GabblePresence *presence,
void gabble_presence_set_capabilities (GabblePresence *presence,
const gchar *resource,
const GabbleCapabilitySet *cap_set,
+ const GPtrArray *data_forms,
guint serial);
gboolean gabble_presence_has_cap (GabblePresence *presence, const gchar *ns);
GabbleCapabilitySet *gabble_presence_dup_caps (GabblePresence *presence);
const GabbleCapabilitySet *gabble_presence_peek_caps (GabblePresence *presence);
+GPtrArray *gabble_presence_peek_data_forms (GabblePresence *presence);
gboolean gabble_presence_has_resources (GabblePresence *self);
diff --git a/tests/test-presence.c b/tests/test-presence.c
index 7b9e423a..8319cb2d 100644
--- a/tests/test-presence.c
+++ b/tests/test-presence.c
@@ -20,6 +20,7 @@ big_test_of_doom (void)
GabblePresence *presence;
GabbleCapabilitySet *cap_set;
time_t now = time (NULL);
+ GPtrArray *data_forms = g_ptr_array_new ();
/* When we create a new presence, we know nothing about the contact in
* question's presence.
@@ -138,7 +139,7 @@ big_test_of_doom (void)
GABBLE_PRESENCE_AVAILABLE, "dingoes", -1, NULL, now));
cap_set = gabble_capability_set_new ();
gabble_capability_set_add (cap_set, NS_GOOGLE_FEAT_VOICE);
- gabble_presence_set_capabilities (presence, "bar", cap_set, 0);
+ gabble_presence_set_capabilities (presence, "bar", cap_set, data_forms, 0);
gabble_capability_set_free (cap_set);
/* no resource with non-negative priority has the Google voice cap */
@@ -149,7 +150,7 @@ big_test_of_doom (void)
/* give voice cap to first resource */
cap_set = gabble_capability_set_new ();
gabble_capability_set_add (cap_set, NS_GOOGLE_FEAT_VOICE);
- gabble_presence_set_capabilities (presence, "foo", cap_set, 0);
+ gabble_presence_set_capabilities (presence, "foo", cap_set, data_forms, 0);
gabble_capability_set_free (cap_set);
/* resource has voice cap */
@@ -169,6 +170,7 @@ big_test_of_doom (void)
gabble_capability_set_predicate_has, NS_GOOGLE_FEAT_VOICE);
g_assert (NULL == resource);
+ g_ptr_array_unref (data_forms);
g_object_unref (presence);
}