Bug 624473: GDBusSubtreeIntrospectFunc return type

Return a NULL terminated C array instead of a GPtrArray

Also, document that %NULL is a permitted return value and clarify its
meaning.

Finally, avoid calling the enumeration function during dispatch when the
G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES flag was given.
This commit is contained in:
Ryan Lortie 2010-07-15 16:26:42 -04:00
parent 48b1fe948c
commit e6b5546cf5
3 changed files with 74 additions and 54 deletions

View File

@ -5167,7 +5167,7 @@ handle_subtree_introspect (GDBusConnection *connection,
const gchar *sender;
const gchar *requested_object_path;
const gchar *requested_node;
GPtrArray *interfaces;
GDBusInterfaceInfo **interfaces;
guint n;
gchar **subnode_paths;
@ -5209,18 +5209,14 @@ handle_subtree_introspect (GDBusConnection *connection,
es->user_data);
if (interfaces != NULL)
{
if (interfaces->len > 0)
{
/* we're in business */
introspect_append_standard_interfaces (s);
introspect_append_standard_interfaces (s);
for (n = 0; n < interfaces->len; n++)
{
const GDBusInterfaceInfo *interface_info = interfaces->pdata[n];
g_dbus_interface_info_generate_xml (interface_info, 2, s);
}
for (n = 0; interfaces[n] != NULL; n++)
{
g_dbus_interface_info_generate_xml (interfaces[n], 2, s);
g_dbus_interface_info_unref (interfaces[n]);
}
g_ptr_array_unref (interfaces);
g_free (interfaces);
}
/* then include <node> entries from the Subtree for the root */
@ -5265,12 +5261,11 @@ handle_subtree_method_invocation (GDBusConnection *connection,
const gchar *requested_object_path;
const gchar *requested_node;
gboolean is_root;
gchar **children;
const GDBusInterfaceInfo *interface_info;
const GDBusInterfaceVTable *interface_vtable;
gpointer interface_user_data;
guint n;
GPtrArray *interfaces;
GDBusInterfaceInfo **interfaces;
gboolean is_property_get;
gboolean is_property_set;
gboolean is_property_get_all;
@ -5298,19 +5293,29 @@ handle_subtree_method_invocation (GDBusConnection *connection,
is_property_get_all = TRUE;
}
children = es->vtable->enumerate (es->connection,
sender,
es->object_path,
es->user_data);
if (!is_root)
{
requested_node = strrchr (requested_object_path, '/') + 1;
/* If not dynamic, skip if requested node is not part of children */
if (!(es->flags & G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES) &&
!_g_strv_has_string ((const gchar * const *) children, requested_node))
goto out;
if (~es->flags & G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES)
{
/* We don't want to dispatch to unenumerated
* nodes, so ensure that the child exists.
*/
gchar **children;
gboolean exists;
children = es->vtable->enumerate (es->connection,
sender,
es->object_path,
es->user_data);
exists = _g_strv_has_string ((const gchar * const *) children, requested_node);
g_strfreev (children);
if (!exists)
goto out;
}
}
else
{
@ -5323,13 +5328,15 @@ handle_subtree_method_invocation (GDBusConnection *connection,
requested_object_path,
requested_node,
es->user_data);
g_assert (interfaces != NULL);
if (interfaces == NULL)
goto out;
interface_info = NULL;
for (n = 0; n < interfaces->len; n++)
for (n = 0; interfaces[n] != NULL; n++)
{
const GDBusInterfaceInfo *id_n = (const GDBusInterfaceInfo *) interfaces->pdata[n];
if (g_strcmp0 (id_n->name, interface_name) == 0)
interface_info = id_n;
if (g_strcmp0 (interfaces[n]->name, interface_name) == 0)
interface_info = interfaces[n];
}
/* dispatch the call if the user wants to handle it */
@ -5371,11 +5378,10 @@ handle_subtree_method_invocation (GDBusConnection *connection,
g_assert_not_reached ();
/* see if the object supports this interface at all */
for (n = 0; n < interfaces->len; n++)
for (n = 0; interfaces[n] != NULL; n++)
{
const GDBusInterfaceInfo *id_n = (const GDBusInterfaceInfo *) interfaces->pdata[n];
if (g_strcmp0 (id_n->name, interface_name) == 0)
interface_info = id_n;
if (g_strcmp0 (interfaces[n]->name, interface_name) == 0)
interface_info = interfaces[n];
}
/* Fail with org.freedesktop.DBus.Error.InvalidArgs if the user-code
@ -5437,8 +5443,12 @@ handle_subtree_method_invocation (GDBusConnection *connection,
out:
if (interfaces != NULL)
g_ptr_array_unref (interfaces);
g_strfreev (children);
{
for (n = 0; interfaces[n] != NULL; n++)
g_dbus_interface_info_unref (interfaces[n]);
g_free (interfaces);
}
return handled;
}

View File

@ -325,16 +325,29 @@ typedef gchar** (*GDBusSubtreeEnumerateFunc) (GDBusConnection *connection,
*
* The type of the @introspect function in #GDBusSubtreeVTable.
*
* Returns: A newly-allocated #GPtrArray with pointers to #GDBusInterfaceInfo describing
* the interfaces implemented by @node.
* This function should return %NULL to indicate that there is no object
* at this node.
*
* If this function returns non-%NULL, the return value is expected to
* be a %NULL-terminated array of pointers to #GDBusInterfaceInfo
* structures describing the interfaces implemented by @node. This
* array will have g_dbus_interface_info_unref() called on each item
* before being freed with g_free().
*
* The difference between returning %NULL and an array containing zero
* items is that the standard DBus interfaces will returned to the
* remote introspector in the empty array case, but not in the %NULL
* case.
*
* Returns: A %NULL-terminated array of pointers to #GDBusInterfaceInfo, or %NULL.
*
* Since: 2.26
*/
typedef GPtrArray *(*GDBusSubtreeIntrospectFunc) (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *node,
gpointer user_data);
typedef GDBusInterfaceInfo ** (*GDBusSubtreeIntrospectFunc) (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *node,
gpointer user_data);
/**
* GDBusSubtreeDispatchFunc:

View File

@ -614,37 +614,38 @@ subtree_enumerate (GDBusConnection *connection,
}
/* Only allows certain objects, and aborts on unknowns */
static GPtrArray *
static GDBusInterfaceInfo **
subtree_introspect (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *node,
gpointer user_data)
{
GPtrArray *interfaces;
const GDBusInterfaceInfo *interfaces[2] = {
NULL /* filled in below */, NULL
};
/* VPs implement the Foo interface, EVPs implement the Bar interface. The root
* does not implement any interfaces
*/
interfaces = g_ptr_array_new ();
if (g_str_has_prefix (node, "vp"))
{
g_ptr_array_add (interfaces, (gpointer) &foo_interface_info);
interfaces[0] = &foo_interface_info;
}
else if (g_str_has_prefix (node, "evp"))
{
g_ptr_array_add (interfaces, (gpointer) &bar_interface_info);
interfaces[0] = &bar_interface_info;
}
else if (g_strcmp0 (node, "/") == 0)
{
/* do nothing */
return NULL;
}
else
{
g_assert_not_reached ();
}
return interfaces;
return g_memdup (interfaces, 2 * sizeof (void *));
}
static const GDBusInterfaceVTable *
@ -691,20 +692,16 @@ dynamic_subtree_enumerate (GDBusConnection *connection,
}
/* Allow all objects to be introspected */
static GPtrArray *
static GDBusInterfaceInfo **
dynamic_subtree_introspect (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *node,
gpointer user_data)
{
GPtrArray *interfaces;
const GDBusInterfaceInfo *interfaces[2] = { &dyna_interface_info, NULL };
/* All nodes (including the root node) implements the Dyna interface */
interfaces = g_ptr_array_new ();
g_ptr_array_add (interfaces, (gpointer) &dyna_interface_info);
return interfaces;
return g_memdup (interfaces, 2 * sizeof (void *));
}
static const GDBusInterfaceVTable *