GApplication: Allow multiple parameters for D-Bus activation

D-Bus Activation allows passing an array of parameters. Allow apps to
export actions that accept tuples to match the number of elements in the
parameters so the full potential of the D-Bus interface can be used.

Closes: https://gitlab.gnome.org/GNOME/glib/-/issues/3333
This commit is contained in:
Julian Sparber 2024-04-28 16:31:13 +02:00
parent 5488829638
commit 0144feb41f
2 changed files with 98 additions and 3 deletions

View File

@ -291,8 +291,6 @@ g_application_impl_method_call (GDBusConnection *connection,
/* Only on the freedesktop interface */
g_variant_get (parameters, "(&sav@a{sv})", &name, &iter, &platform_data);
g_variant_iter_next (iter, "v", &parameter);
g_variant_iter_free (iter);
/* Check the action exists and the parameter type matches. */
if (!g_action_group_query_action (impl->exported_actions,
@ -306,6 +304,28 @@ g_application_impl_method_call (GDBusConnection *connection,
return;
}
/* Accept multiple parameters as a tuple with the exact number of parameters */
if (g_variant_iter_n_children (iter) > 1)
{
GVariant *value = NULL;
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
while (g_variant_iter_loop (iter, "v", &value))
{
g_variant_builder_add_value (&builder, value);
}
parameter = g_variant_ref_sink (g_variant_builder_end (&builder));
}
else
{
g_variant_iter_next (iter, "v", &parameter);
}
g_variant_iter_free (iter);
if (!((parameter_type == NULL && parameter == NULL) ||
(parameter_type != NULL && parameter != NULL && g_variant_is_of_type (parameter, parameter_type))))
{

View File

@ -1734,7 +1734,7 @@ test_dbus_activate_action (void)
{
GDBusMessage *message; /* (not nullable) (owned) */
guint n_expected_activations;
} messages[6];
} messages[12];
gsize i;
g_test_summary ("Test that calling the ActivateAction D-Bus method works");
@ -1796,6 +1796,79 @@ test_dbus_activate_action (void)
g_dbus_message_set_body (messages[5].message, g_variant_new ("(sava{sv})", "nonexistent", NULL, NULL));
messages[5].n_expected_activations = 0;
/* Action with tuple as parameter given as two items to the interface */
g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
g_variant_builder_add (&builder, "v", g_variant_new_string ("first"));
g_variant_builder_add (&builder, "v", g_variant_new_string ("second"));
messages[6].message = g_dbus_message_new_method_call ("org.gtk.TestApplication.ActivateAction",
"/org/gtk/TestApplication/ActivateAction",
"org.freedesktop.Application",
"ActivateAction");
g_dbus_message_set_body (messages[6].message, g_variant_new ("(sava{sv})", "multi", &builder, NULL));
messages[6].n_expected_activations = 1;
/* Action with tuple as parameter given as two items to the interface but with a wrong type */
g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
g_variant_builder_add (&builder, "v", g_variant_new_string ("first"));
g_variant_builder_add (&builder, "v", g_variant_new_uint32 (42));
messages[7].message = g_dbus_message_new_method_call ("org.gtk.TestApplication.ActivateAction",
"/org/gtk/TestApplication/ActivateAction",
"org.freedesktop.Application",
"ActivateAction");
g_dbus_message_set_body (messages[7].message, g_variant_new ("(sava{sv})", "multi", &builder, NULL));
messages[7].n_expected_activations = 0;
/* Action with tuple as parameter given as a single item to the interface */
g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
g_variant_builder_add (&builder, "v", g_variant_new ("(ss)", "first", "second"));
messages[8].message = g_dbus_message_new_method_call ("org.gtk.TestApplication.ActivateAction",
"/org/gtk/TestApplication/ActivateAction",
"org.freedesktop.Application",
"ActivateAction");
g_dbus_message_set_body (messages[8].message, g_variant_new ("(sava{sv})", "multi", &builder, NULL));
messages[8].n_expected_activations = 1;
/* Action with tuple as parameter given as a single item to the interface but with additional items */
g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
g_variant_builder_add (&builder, "v", g_variant_new ("(ss)", "first", "second"));
g_variant_builder_add (&builder, "v", g_variant_new_uint32 (42));
g_variant_builder_add (&builder, "v", g_variant_new_uint32 (42));
messages[9].message = g_dbus_message_new_method_call ("org.gtk.TestApplication.ActivateAction",
"/org/gtk/TestApplication/ActivateAction",
"org.freedesktop.Application",
"ActivateAction");
g_dbus_message_set_body (messages[9].message, g_variant_new ("(sava{sv})", "multi", &builder, NULL));
messages[9].n_expected_activations = 0;
/* Action with tuple with single item as parameter */
g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
g_variant_builder_add (&builder, "v", g_variant_new ("(s)", "first"));
messages[10].message = g_dbus_message_new_method_call ("org.gtk.TestApplication.ActivateAction",
"/org/gtk/TestApplication/ActivateAction",
"org.freedesktop.Application",
"ActivateAction");
g_dbus_message_set_body (messages[10].message, g_variant_new ("(sava{sv})", "single", &builder, NULL));
messages[10].n_expected_activations = 1;
/* Action with tuple with single item as parameter with additional items */
g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
g_variant_builder_add (&builder, "v", g_variant_new ("(s)", "first"));
g_variant_builder_add (&builder, "v", g_variant_new_uint32 (42));
g_variant_builder_add (&builder, "v", g_variant_new_uint32 (43));
messages[11].message = g_dbus_message_new_method_call ("org.gtk.TestApplication.ActivateAction",
"/org/gtk/TestApplication/ActivateAction",
"org.freedesktop.Application",
"ActivateAction");
g_dbus_message_set_body (messages[11].message, g_variant_new ("(sava{sv})", "single", &builder, NULL));
messages[11].n_expected_activations = 0;
/* Try each message */
bus = g_test_dbus_new (G_TEST_DBUS_NONE);
g_test_dbus_up (bus);
@ -1808,6 +1881,8 @@ test_dbus_activate_action (void)
{
{ "undo", dbus_activate_action_cb, NULL, NULL, NULL, { 0 } },
{ "lang", dbus_activate_action_cb, "s", "'latin'", NULL, { 0 } },
{ "single", dbus_activate_action_cb, "(s)", NULL, NULL, { 0 } },
{ "multi", dbus_activate_action_cb, "(ss)", NULL, NULL, { 0 } },
};
guint n_activations = 0;