Bug 42288 - Review Chan.I.FileTransfer.Metadata
Summary: Review Chan.I.FileTransfer.Metadata
Status: RESOLVED FIXED
Alias: None
Product: Telepathy
Classification: Unclassified
Component: gabble (show other bugs)
Version: git master
Hardware: Other All
: medium normal
Assignee: Telepathy bugs list
QA Contact: Telepathy bugs list
URL: http://cgit.freedesktop.org/~jonny/te...
Whiteboard: review+
Keywords: patch
Depends on: 39644
Blocks:
  Show dependency treegraph
 
Reported: 2011-10-26 11:08 UTC by Jonny Lamb
Modified: 2011-11-16 00:52 UTC (History)
1 user (show)

See Also:
i915 platform:
i915 features:


Attachments

Description Jonny Lamb 2011-10-26 11:08:01 UTC
I've implemented this cool cool interface.

Here's a proto-xep too!!!!!

http://people.collabora.com/~jonny/extensions/proto-ft-metadata.html
Comment 1 Will Thompson 2011-10-31 04:39:12 UTC
+  service_name = g_strdup (field->raw_value_contents[0]);

If the form has a ServiceName field but no <value/> elements, will parsing the form fail, or will this crash?


+  if (field == NULL)
+    {
+      DEBUG ("ServiceName propery not present in data form; odd...");
+      goto out;
+    }
+
+  service_name = g_strdup (field->raw_value_contents[0]);
+
+out:

Eh, why not

   if (field != NULL)
     service_name = ...
   else
     DEBUG ("ServiceName...");

rather than goto? I don't think the goto makes it clearer.

Blah, if ServiceName is not going to be stashed in the same data form as the metadata, then it shouldn't be a data form. it should just be

  <service-name xmlns="im:telepathy:file-transfer:service" name='com.example.HiMum'/>

and… im: is not a URI scheme. http://telepathy.im/...

+      WockyStanza *tmp = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
+          WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL,
+          '(', "x",
+            ':', NS_X_DATA,
+            '@', "type", "result",
+            '(', "field",
+              '@', "var", "FORM_TYPE",
+              '@', "type", "hidden",
+              '(', "value",
+                '$', NS_TP_FT_METADATA_SERVICE,
+              ')',
+            ')',
+            '(', "field",
+              '@', "var", "ServiceName",
+              '(', "value",
+                '$', self->priv->service_name,
+              ')',
+            ')',
+          ')',
+          NULL);
+      WockyNode *x = wocky_node_get_first_child (wocky_stanza_get_top_node (tmp));
+      WockyNodeTree *tree = wocky_node_tree_new_from_node (x);
+
+      wocky_node_add_node_tree (file, tree);
+      g_object_unref (tree);
+      g_object_unref (tmp);

Ugh this is dumb. There should be a wocky_node_tree_build().


+          WockyNode *field = wocky_node_add_child (x, "field");
+
+          wocky_node_set_attribute (field, "var", (const gchar *) key);
+
+          wocky_node_add_child_with_content (field, "value",
+              (const gchar *) val);

wocky_node_add_build (x,
  '(', "field",
    '@', "var", key,
    '(', "value",
      '$', val,
    ')',
  ')', NULL);

or is that less clear?

I don't really see why the metadata-specific test is the one which explicitly sends no metadata. I guess it's testing edge cases…

+        requests_iface = dbus.Interface(self.conn, cs.CONN_IFACE_REQUESTS)

Just use self.conn.Requests

+add_file_transfer_channel_class (GPtrArray *arr,
+    gboolean metadata)

Giving the variable a more descriptive name like "include_metadata_properties" might be nice.

+      service_name_value = tp_g_value_slice_new (G_TYPE_STRING);
+      g_value_set_string (service_name_value, service_name_str);

is secret code for tp_g_value_slice_new_string (service_name_str);

The huge test is huge.


    if expect_disco:
        # Gabble looks up our capabilities
        event = q.expect('stream-iq', to=contact, query_ns=ns.DISCO_INFO)
        query_node = xpath.queryForNodes('/iq/query', event.stanza)[0]
        assert query_node.attributes['node'] == \
            client + '#' + c['ver']

        # send good reply
        result = make_result_iq(stream, event.stanza)
        query = result.firstChildElement()
        query['node'] = client + '#' + c['ver']

        for f in features:
            feature = query.addElement('feature')
            feature['var'] = f

        stream.send(result)

This is secret code for caps_helper.expect_disco(); caps_helper.send_disco_reply(). In fact, most of receive_caps in that test is just caps_helper.presence_and_disco().

All the dbus.Dictionary(a.items() + {...}.items()) stuff is really noisy. def dict_union(a, b) maybe?

The test looks fine, I guess, it's just hard to read.
Comment 2 Jonny Lamb 2011-10-31 07:53:46 UTC
(In reply to comment #1)
> +  service_name = g_strdup (field->raw_value_contents[0]);
> 
> If the form has a ServiceName field but no <value/> elements, will parsing the
> form fail, or will this crash?

Let's be sure. I added another patch.

> +  if (field == NULL)
> +    {
> +      DEBUG ("ServiceName propery not present in data form; odd...");
> +      goto out;
> +    }
> +
> +  service_name = g_strdup (field->raw_value_contents[0]);
> +
> +out:
> 
> Eh, why not
> 
>    if (field != NULL)
>      service_name = ...
>    else
>      DEBUG ("ServiceName...");
> 
> rather than goto? I don't think the goto makes it clearer.

OK, done.

> Blah, if ServiceName is not going to be stashed in the same data form as the
> metadata, then it shouldn't be a data form. it should just be
> 
>   <service-name xmlns="im:telepathy:file-transfer:service"
> name='com.example.HiMum'/>

We discussed this in real life and I thought you conceded that using another data form just made things easier?

> and… im: is not a URI scheme. http://telepathy.im/...

Okay. :-)

> +      WockyStanza *tmp = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
> +          WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL,
> +          '(', "x",
> +            ':', NS_X_DATA,
> +            '@', "type", "result",
> +            '(', "field",
> +              '@', "var", "FORM_TYPE",
> +              '@', "type", "hidden",
> +              '(', "value",
> +                '$', NS_TP_FT_METADATA_SERVICE,
> +              ')',
> +            ')',
> +            '(', "field",
> +              '@', "var", "ServiceName",
> +              '(', "value",
> +                '$', self->priv->service_name,
> +              ')',
> +            ')',
> +          ')',
> +          NULL);
> +      WockyNode *x = wocky_node_get_first_child (wocky_stanza_get_top_node
> (tmp));
> +      WockyNodeTree *tree = wocky_node_tree_new_from_node (x);
> +
> +      wocky_node_add_node_tree (file, tree);
> +      g_object_unref (tree);
> +      g_object_unref (tmp);
> 
> Ugh this is dumb. There should be a wocky_node_tree_build().

I agree. I opened bug #42433.

> +          WockyNode *field = wocky_node_add_child (x, "field");
> +
> +          wocky_node_set_attribute (field, "var", (const gchar *) key);
> +
> +          wocky_node_add_child_with_content (field, "value",
> +              (const gchar *) val);
> 
> wocky_node_add_build (x,
>   '(', "field",
>     '@', "var", key,
>     '(', "value",
>       '$', val,
>     ')',
>   ')', NULL);
> 
> or is that less clear?

Well let's do it and see.

> I don't really see why the metadata-specific test is the one which explicitly
> sends no metadata. I guess it's testing edge cases…

Yes. It tests that no dataform is sent. I didn't want it to send an empty dataform in that case.

> +        requests_iface = dbus.Interface(self.conn, cs.CONN_IFACE_REQUESTS)
> 
> Just use self.conn.Requests

OK!

> +add_file_transfer_channel_class (GPtrArray *arr,
> +    gboolean metadata)
> 
> Giving the variable a more descriptive name like "include_metadata_properties"
> might be nice.

OK!

> +      service_name_value = tp_g_value_slice_new (G_TYPE_STRING);
> +      g_value_set_string (service_name_value, service_name_str);
> 
> is secret code for tp_g_value_slice_new_string (service_name_str);

YEAAAHHH.

> The huge test is huge.

Why not?

>     if expect_disco:
>         # Gabble looks up our capabilities
>         event = q.expect('stream-iq', to=contact, query_ns=ns.DISCO_INFO)
>         query_node = xpath.queryForNodes('/iq/query', event.stanza)[0]
>         assert query_node.attributes['node'] == \
>             client + '#' + c['ver']
> 
>         # send good reply
>         result = make_result_iq(stream, event.stanza)
>         query = result.firstChildElement()
>         query['node'] = client + '#' + c['ver']
> 
>         for f in features:
>             feature = query.addElement('feature')
>             feature['var'] = f
> 
>         stream.send(result)
> 
> This is secret code for caps_helper.expect_disco();
> caps_helper.send_disco_reply(). In fact, most of receive_caps in that test is
> just caps_helper.presence_and_disco().

Yep, I replaced lots of it with just that.

> All the dbus.Dictionary(a.items() + {...}.items()) stuff is really noisy. def
> dict_union(a, b) maybe?

I guess, done.

Branch updated, thanks for the review!
Comment 3 Will Thompson 2011-11-09 08:48:40 UTC
> ft-client-caps test: change client nameft-metadata
> 
> I've no idea why but if caps/tube-caps.py is run before this test (it
> has the same idea and design as this test was copied from it) then
> this one fails due to the same client name?! Another day...

I think this is probably because the caps end up in the cache so Gabble doesn't make the disco query that the test expects.

(In reply to comment #2)
> (In reply to comment #1)
> > +  if (field == NULL)
> > +    {
> > +      DEBUG ("ServiceName propery not present in data form; odd...");
> > +      goto out;
> > +    }
> > +
> > +  service_name = g_strdup (field->raw_value_contents[0]);
> > +
> > +out:
> > 
> > Eh, why not
> > 
> >    if (field != NULL)
> >      service_name = ...
> >    else
> >      DEBUG ("ServiceName...");
> > 
> > rather than goto? I don't think the goto makes it clearer.
> 
> OK, done.

No it's not, but in the course of fixing the above complaint you made the goto justify its own existence. :)

> > Blah, if ServiceName is not going to be stashed in the same data form as the
> > metadata, then it shouldn't be a data form. it should just be
> > 
> >   <service-name xmlns="im:telepathy:file-transfer:service"
> > name='com.example.HiMum'/>
> 
> We discussed this in real life and I thought you conceded that using another
> data form just made things easier?

It means one less XEP to write I guess, but it offends me at some level. :)

> > and… im: is not a URI scheme. http://telepathy.im/...
> 
> Okay. :-)

I hate to be that guy, but I've just noticed that elsewhere we use URLs under http://telepathy.freedesktop.org/xmpp/ which actually points to documents. So you could put the proto-XEP there and use it as the capability URI maybe? Sorry :/

> > wocky_node_add_build (x,
> >   '(', "field",
> >     '@', "var", key,
> >     '(', "value",
> >       '$', val,
> >     ')',
> >   ')', NULL);
> > 
> > or is that less clear?
> 
> Well let's do it and see.

I like it. Particularly getting rid of the casts.

> > I don't really see why the metadata-specific test is the one which explicitly
> > sends no metadata. I guess it's testing edge cases…
> 
> Yes. It tests that no dataform is sent. I didn't want it to send an empty
> dataform in that case.

Ah, okay!
Comment 4 Jonny Lamb 2011-11-09 09:35:15 UTC
(In reply to comment #3)
> I hate to be that guy, but I've just noticed that elsewhere we use URLs under
> http://telepathy.freedesktop.org/xmpp/ which actually points to documents. So
> you could put the proto-XEP there and use it as the capability URI maybe? Sorry
> :/

The worst guy! Updated. I should put the proto XEP there too.
Comment 5 Will Thompson 2011-11-10 05:41:48 UTC
+      type="a{sas}" tp:type="Metadata" access="readwrite"

+    <tp:mapping name="Metadata" type="a{ua{sv}}">

Le whut.

I wonder if this will break if I pass

 Metadata: {
   'foo': [],
 }
Comment 6 Jonny Lamb 2011-11-11 03:12:29 UTC
(In reply to comment #5)
> +      type="a{sas}" tp:type="Metadata" access="readwrite"
> 
> +    <tp:mapping name="Metadata" type="a{ua{sv}}">
> 
> Le whut.

This'll be fixed when we depend on new enough tp-glib and we can remove this example. I'll ignore it for now (fixed in tp-spec master).

> I wonder if this will break if I pass
> 
>  Metadata: {
>    'foo': [],
>  }

I added a test. It initially didn't pass due to caps-helper stuff but it does now.
Comment 7 Will Thompson 2011-11-15 06:57:21 UTC
looks lush.
Comment 8 Jonny Lamb 2011-11-16 00:52:53 UTC
le merged, thanks.


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.