From 7384e372f04eae356523efb29e279ca0c768bad6 Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Wed, 10 May 2017 13:51:19 +0200 Subject: [PATCH] gio: Add hack to close up dbus-daemon race If gio open exits before the program it starts fully activates, then the dbus-daemon may avoid doing the activating method call. This commit works around the problem by pinging the activated application, and waiting for a reply. Same workaround is used in gtk-launch and was used in gvfs-open before it was replaced by gio open. https://bugzilla.gnome.org/show_bug.cgi?id=780296 --- gio/gio-tool-open.c | 89 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/gio/gio-tool-open.c b/gio/gio-tool-open.c index fc74186f7..742880e35 100644 --- a/gio/gio-tool-open.c +++ b/gio/gio-tool-open.c @@ -20,6 +20,7 @@ #include "config.h" #include +#include #include #include "gio-tool.h" @@ -29,6 +30,67 @@ static const GOptionEntry entries[] = { { NULL } }; +static gboolean +get_bus_name_and_path_from_uri (const char *uri, + char **bus_name_out, + char **object_path_out) +{ + GAppInfo *app_info = NULL; + char *bus_name = NULL; + char *object_path = NULL; + char *uri_scheme; + const char *filename; + char *basename = NULL; + char *p; + gboolean got_name = FALSE; + + uri_scheme = g_uri_parse_scheme (uri); + if (uri_scheme && uri_scheme[0] != '\0') + app_info = g_app_info_get_default_for_uri_scheme (uri_scheme); + g_free (uri_scheme); + + if (app_info == NULL) + { + GFile *file; + + file = g_file_new_for_uri (uri); + app_info = g_file_query_default_handler (file, NULL, NULL); + g_object_unref (file); + } + + if (app_info == NULL || !G_IS_DESKTOP_APP_INFO (app_info) || + !g_desktop_app_info_get_boolean (G_DESKTOP_APP_INFO (app_info), "DBusActivatable")) + goto out; + + filename = g_desktop_app_info_get_filename (G_DESKTOP_APP_INFO (app_info)); + if (filename == NULL) + goto out; + + basename = g_path_get_basename (filename); + if (!g_str_has_suffix (basename, ".desktop")) + goto out; + + basename[strlen (basename) - strlen (".desktop")] = '\0'; + if (!g_dbus_is_name (basename)) + goto out; + + bus_name = g_strdup (basename); + object_path = g_strdup_printf ("/%s", bus_name); + for (p = object_path; *p != '\0'; p++) + if (*p == '.') + *p = '/'; + + *bus_name_out = g_steal_pointer (&bus_name); + *object_path_out = g_steal_pointer (&object_path); + got_name = TRUE; + +out: + g_clear_object (&app_info); + g_clear_pointer (&basename, g_free); + + return got_name; +} + int handle_open (int argc, char *argv[], gboolean do_help) { @@ -92,6 +154,33 @@ handle_open (int argc, char *argv[], gboolean do_help) success = FALSE; } + /* FIXME: This chunk of madness is a workaround for a dbus-daemon bug. + * See https://bugzilla.gnome.org/show_bug.cgi?id=780296 + */ + if (res) + { + char *bus_name = NULL; + char *object_path = NULL; + + if (get_bus_name_and_path_from_uri (uri, &bus_name, &object_path)) + { + GDBusConnection *connection; + connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); + + if (connection) + g_dbus_connection_call_sync (connection, + bus_name, + object_path, + "org.freedesktop.DBus.Peer", + "Ping", + NULL, NULL, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL); + g_clear_object (&connection); + g_free (bus_name); + g_free (object_path); + } + } + g_object_unref (file); g_free (uri); }