diff options
author | Jonny Lamb <jonny.lamb@collabora.co.uk> | 2011-08-31 08:58:55 +0100 |
---|---|---|
committer | Jonny Lamb <jonny.lamb@collabora.co.uk> | 2011-09-01 13:26:37 +0100 |
commit | d887fdc2d23bf00322c9923e8eead7c5f0607302 (patch) | |
tree | c546b36d7d3c6d870f71d1ff31a720a43bd63495 | |
parent | 5dcf95eaf432b5af1edf82e87f40f795a3265a35 (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.c | 5 | ||||
-rw-r--r-- | src/connection.c | 21 | ||||
-rw-r--r-- | src/presence-cache.c | 13 | ||||
-rw-r--r-- | src/presence.c | 35 | ||||
-rw-r--r-- | src/presence.h | 2 | ||||
-rw-r--r-- | tests/test-presence.c | 6 |
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); } |