From 95d71301b5a843bc6a8e6b9d06ec72215805927e Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Wed, 25 Apr 2012 15:57:13 +0100 Subject: [PATCH 12/16] Add and test functions to check for particular file transfer properties These functions make the simplifying assumption that all of these properties are orthogonal, so if both (say) InitialOffset and Description are supported, then they'll be supported in the same requestable channel class. This is about the best you can do without exposing the requestable channel classes themselves as API and having applications iterate through them, which seems lower-level than we want. Signed-off-by: Simon McVittie Bug: https://bugs.freedesktop.org/show_bug.cgi?id=48780 --- docs/reference/telepathy-glib-sections.txt | 4 + telepathy-glib/capabilities.c | 166 +++++++++++++++++++++++++++- telepathy-glib/capabilities.h | 7 ++ tests/capabilities.c | 140 ++++++++++++++++++++++- 4 files changed, 309 insertions(+), 8 deletions(-) diff --git a/docs/reference/telepathy-glib-sections.txt b/docs/reference/telepathy-glib-sections.txt index 2b0df67..b4ddbef 100644 --- a/docs/reference/telepathy-glib-sections.txt +++ b/docs/reference/telepathy-glib-sections.txt @@ -4996,6 +4996,10 @@ tp_capabilities_supports_sms tp_capabilities_supports_audio_call tp_capabilities_supports_audio_video_call tp_capabilities_supports_file_transfer +tp_capabilities_supports_file_transfer_description +tp_capabilities_supports_file_transfer_initial_offset +tp_capabilities_supports_file_transfer_timestamp +tp_capabilities_supports_file_transfer_uri tp_capabilities_supports_stream_tubes tp_capabilities_supports_dbus_tubes tp_capabilities_supports_contact_search diff --git a/telepathy-glib/capabilities.c b/telepathy-glib/capabilities.c index 72f14a4..5f1b85d 100644 --- a/telepathy-glib/capabilities.c +++ b/telepathy-glib/capabilities.c @@ -571,6 +571,95 @@ tp_capabilities_supports_audio_video_call (TpCapabilities *self, return supports_call_full (self, handle_type, TRUE, TRUE); } +typedef enum { + FT_CAP_FLAGS_NONE = 0, + FT_CAP_FLAG_URI = (1<<0), + FT_CAP_FLAG_OFFSET = (1<<1), + FT_CAP_FLAG_DATE = (1<<2), + FT_CAP_FLAG_DESCRIPTION = (1<<3) +} FTCapFlags; + +static gboolean +supports_file_transfer (TpCapabilities *self, + FTCapFlags flags) +{ + guint i; + + g_return_val_if_fail (TP_IS_CAPABILITIES (self), FALSE); + + for (i = 0; i < self->priv->classes->len; i++) + { + GValueArray *arr = g_ptr_array_index (self->priv->classes, i); + GHashTable *fixed; + const gchar *chan_type; + TpHandleType handle_type; + gboolean valid; + guint n_fixed = 2; + const gchar * const *allowed; + + tp_value_array_unpack (arr, 2, &fixed, &allowed); + + chan_type = tp_asv_get_string (fixed, TP_PROP_CHANNEL_CHANNEL_TYPE); + + if (tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER)) + continue; + + handle_type = tp_asv_get_uint32 (fixed, + TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, &valid); + + if (!valid) + continue; + + if (handle_type != TP_HANDLE_TYPE_CONTACT) + continue; + + /* ContentType, Filename, Size are mandatory. In principle we could check + * that the CM allows them, but not allowing them would be ridiculous, + * so we don't. + */ + + if ((flags & FT_CAP_FLAG_DESCRIPTION) != 0) + { + /* Description makes no sense as a fixed property so we assume + * the CM won't be ridiculous */ + if (!tp_strv_contains (allowed, + TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_DESCRIPTION)) + continue; + } + + if ((flags & FT_CAP_FLAG_DATE) != 0) + { + /* makes no sense as a fixed property */ + if (!tp_strv_contains (allowed, + TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_DATE)) + continue; + } + + if ((flags & FT_CAP_FLAG_URI) != 0) + { + /* makes no sense as a fixed property */ + if (!tp_strv_contains (allowed, + TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_URI)) + continue; + } + + if ((flags & FT_CAP_FLAG_OFFSET) != 0) + { + /* makes no sense as a fixed property */ + if (!tp_strv_contains (allowed, + TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_INITIAL_OFFSET)) + continue; + } + + if (n_fixed != tp_asv_size (fixed)) + continue; + + return TRUE; + } + + return FALSE; +} + /** * tp_capabilities_supports_file_transfer: * @self: a #TpCapabilities object @@ -587,8 +676,81 @@ tp_capabilities_supports_audio_video_call (TpCapabilities *self, gboolean tp_capabilities_supports_file_transfer (TpCapabilities *self) { - return supports_simple_channel (self, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, - TP_HANDLE_TYPE_CONTACT); + return supports_file_transfer (self, FT_CAP_FLAGS_NONE); +} + +/** + * tp_capabilities_supports_file_transfer_uri: + * @self: a #TpCapabilities object + * + * + * + * Returns: %TRUE if requests as described for + * tp_capabilities_supports_file_transfer() can also specify the outgoing + * file's URI + * + * Since: 0.19.UNRELEASED + */ +gboolean +tp_capabilities_supports_file_transfer_uri (TpCapabilities *self) +{ + return supports_file_transfer (self, FT_CAP_FLAG_URI); +} + +/** + * tp_capabilities_supports_file_transfer_description: + * @self: a #TpCapabilities object + * + * + * + * Returns: %TRUE if requests as described for + * tp_capabilities_supports_file_transfer() can also specify the outgoing + * file's description + * + * Since: 0.19.UNRELEASED + */ +gboolean +tp_capabilities_supports_file_transfer_description (TpCapabilities *self) +{ + return supports_file_transfer (self, FT_CAP_FLAG_DESCRIPTION); +} + +/** + * tp_capabilities_supports_file_transfer_initial_offset: + * @self: a #TpCapabilities object + * + * Return whether an initial offset other than 0 can be specified on + * outgoing file transfers. This can be used to resume partial transfers, + * by omitting the part that has already been sent. + * + * Returns: %TRUE if requests as described for + * tp_capabilities_supports_file_transfer() can also specify an + * initial offset greater than 0 + * + * Since: 0.19.UNRELEASED + */ +gboolean +tp_capabilities_supports_file_transfer_initial_offset (TpCapabilities *self) +{ + return supports_file_transfer (self, FT_CAP_FLAG_OFFSET); +} + +/** + * tp_capabilities_supports_file_transfer_timestamp: + * @self: a #TpCapabilities object + * + * + * + * Returns: %TRUE if requests as described for + * tp_capabilities_supports_file_transfer() can also specify the outgoing + * file's timestamp + * + * Since: 0.19.UNRELEASED + */ +gboolean +tp_capabilities_supports_file_transfer_timestamp (TpCapabilities *self) +{ + return supports_file_transfer (self, FT_CAP_FLAG_DATE); } static gboolean diff --git a/telepathy-glib/capabilities.h b/telepathy-glib/capabilities.h index 1d55c1a..5fd8903 100644 --- a/telepathy-glib/capabilities.h +++ b/telepathy-glib/capabilities.h @@ -61,6 +61,13 @@ gboolean tp_capabilities_supports_audio_call (TpCapabilities *self, gboolean tp_capabilities_supports_audio_video_call (TpCapabilities *self, TpHandleType handle_type); gboolean tp_capabilities_supports_file_transfer (TpCapabilities *self); +gboolean tp_capabilities_supports_file_transfer_uri (TpCapabilities *self); +gboolean tp_capabilities_supports_file_transfer_description ( + TpCapabilities *self); +gboolean tp_capabilities_supports_file_transfer_timestamp ( + TpCapabilities *self); +gboolean tp_capabilities_supports_file_transfer_initial_offset ( + TpCapabilities *self); gboolean tp_capabilities_supports_stream_tubes (TpCapabilities *self, TpHandleType handle_type, diff --git a/tests/capabilities.c b/tests/capabilities.c index 61c1ce6..45ee48c 100644 --- a/tests/capabilities.c +++ b/tests/capabilities.c @@ -53,15 +53,19 @@ add_text_chat_class (GPtrArray *classes, } static void -add_ft_class (GPtrArray *classes) +add_ft_class (GPtrArray *classes, + const gchar * const *allowed) { GHashTable *fixed; - const gchar * const allowed[] = { + const gchar * const default_allowed[] = { TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_FILENAME, TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_SIZE, NULL }; GValueArray *arr; + if (allowed == NULL) + allowed = default_allowed; + fixed = tp_asv_new ( TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, @@ -95,7 +99,7 @@ test_basics (Test *test, /* TpCapabilities containing the text chats and ft caps */ classes = g_ptr_array_sized_new (2); add_text_chat_class (classes, TP_HANDLE_TYPE_CONTACT); - add_ft_class (classes); + add_ft_class (classes, NULL); caps = tp_tests_object_new_static_class (TP_TYPE_CAPABILITIES, "channel-classes", classes, @@ -628,7 +632,7 @@ test_supports_room_list (Test *test, /* Does not support room list */ classes = g_ptr_array_sized_new (4); - add_ft_class (classes); + add_ft_class (classes, NULL); caps = tp_tests_object_new_static_class (TP_TYPE_CAPABILITIES, "channel-classes", classes, @@ -645,7 +649,7 @@ test_supports_room_list (Test *test, /* Support room list but no server */ classes = g_ptr_array_sized_new (4); - add_ft_class (classes); + add_ft_class (classes, NULL); add_room_list_class (classes, FALSE, FALSE); caps = tp_tests_object_new_static_class (TP_TYPE_CAPABILITIES, @@ -663,7 +667,7 @@ test_supports_room_list (Test *test, /* Support room list with server */ classes = g_ptr_array_sized_new (4); - add_ft_class (classes); + add_ft_class (classes, NULL); add_room_list_class (classes, TRUE, FALSE); caps = tp_tests_object_new_static_class (TP_TYPE_CAPABILITIES, @@ -961,6 +965,128 @@ test_supports_call (Test *test, g_object_unref (caps); } +static void +test_supports_ft_props (Test *test, + gconstpointer data G_GNUC_UNUSED) +{ + TpCapabilities *caps; + GPtrArray *classes; + const gchar * const allow_uri[] = { TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_URI, + NULL }; + const gchar * const allow_desc[] = { + TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_DESCRIPTION, NULL }; + const gchar * const allow_date[] = { + TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_DATE, NULL }; + const gchar * const allow_initial_offset[] = { + TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_INITIAL_OFFSET, NULL }; + + /* TpCapabilities containing no caps */ + caps = _tp_capabilities_new (NULL, TRUE); + + g_assert (!tp_capabilities_supports_file_transfer (caps)); + g_assert (!tp_capabilities_supports_file_transfer_uri (caps)); + g_assert (!tp_capabilities_supports_file_transfer_description (caps)); + g_assert (!tp_capabilities_supports_file_transfer_timestamp (caps)); + g_assert (!tp_capabilities_supports_file_transfer_initial_offset (caps)); + + g_object_unref (caps); + + classes = g_ptr_array_sized_new (1); + add_ft_class (classes, NULL); + + caps = tp_tests_object_new_static_class (TP_TYPE_CAPABILITIES, + "channel-classes", classes, + "contact-specific", TRUE, + NULL); + + g_boxed_free (TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST, + classes); + + g_assert (tp_capabilities_supports_file_transfer (caps)); + g_assert (!tp_capabilities_supports_file_transfer_uri (caps)); + g_assert (!tp_capabilities_supports_file_transfer_description (caps)); + g_assert (!tp_capabilities_supports_file_transfer_timestamp (caps)); + g_assert (!tp_capabilities_supports_file_transfer_initial_offset (caps)); + + g_object_unref (caps); + + classes = g_ptr_array_sized_new (1); + add_ft_class (classes, allow_uri); + + caps = tp_tests_object_new_static_class (TP_TYPE_CAPABILITIES, + "channel-classes", classes, + "contact-specific", TRUE, + NULL); + + g_boxed_free (TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST, + classes); + + g_assert (tp_capabilities_supports_file_transfer (caps)); + g_assert (tp_capabilities_supports_file_transfer_uri (caps)); + g_assert (!tp_capabilities_supports_file_transfer_description (caps)); + g_assert (!tp_capabilities_supports_file_transfer_timestamp (caps)); + g_assert (!tp_capabilities_supports_file_transfer_initial_offset (caps)); + + g_object_unref (caps); + + classes = g_ptr_array_sized_new (1); + add_ft_class (classes, allow_desc); + + caps = tp_tests_object_new_static_class (TP_TYPE_CAPABILITIES, + "channel-classes", classes, + "contact-specific", TRUE, + NULL); + + g_boxed_free (TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST, + classes); + + g_assert (tp_capabilities_supports_file_transfer (caps)); + g_assert (!tp_capabilities_supports_file_transfer_uri (caps)); + g_assert (tp_capabilities_supports_file_transfer_description (caps)); + g_assert (!tp_capabilities_supports_file_transfer_timestamp (caps)); + g_assert (!tp_capabilities_supports_file_transfer_initial_offset (caps)); + + g_object_unref (caps); + + classes = g_ptr_array_sized_new (1); + add_ft_class (classes, allow_date); + + caps = tp_tests_object_new_static_class (TP_TYPE_CAPABILITIES, + "channel-classes", classes, + "contact-specific", TRUE, + NULL); + + g_boxed_free (TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST, + classes); + + g_assert (tp_capabilities_supports_file_transfer (caps)); + g_assert (!tp_capabilities_supports_file_transfer_uri (caps)); + g_assert (!tp_capabilities_supports_file_transfer_description (caps)); + g_assert (tp_capabilities_supports_file_transfer_timestamp (caps)); + g_assert (!tp_capabilities_supports_file_transfer_initial_offset (caps)); + + g_object_unref (caps); + + classes = g_ptr_array_sized_new (1); + add_ft_class (classes, allow_initial_offset); + + caps = tp_tests_object_new_static_class (TP_TYPE_CAPABILITIES, + "channel-classes", classes, + "contact-specific", TRUE, + NULL); + + g_boxed_free (TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST, + classes); + + g_assert (tp_capabilities_supports_file_transfer (caps)); + g_assert (!tp_capabilities_supports_file_transfer_uri (caps)); + g_assert (!tp_capabilities_supports_file_transfer_description (caps)); + g_assert (!tp_capabilities_supports_file_transfer_timestamp (caps)); + g_assert (tp_capabilities_supports_file_transfer_initial_offset (caps)); + + g_object_unref (caps); +} + int main (int argc, char **argv) @@ -974,6 +1100,8 @@ main (int argc, NULL); g_test_add (TEST_PREFIX "supports", Test, NULL, setup, test_supports, NULL); + g_test_add (TEST_PREFIX "supports/ft-props", Test, NULL, setup, + test_supports_ft_props, NULL); g_test_add (TEST_PREFIX "supports/tube", Test, NULL, setup, test_supports_tube, NULL); g_test_add (TEST_PREFIX "supports/room-list", Test, NULL, setup, -- 1.7.10