From 7bee91695bbe5d9228392e6da496186f02df5c39 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 20 May 2015 16:25:01 -0400 Subject: [PATCH] gvfs-open: add hack to close up dbus-daemon race If gvfs-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. https://bugzilla.gnome.org/show_bug.cgi?id=746534 --- programs/gvfs-open.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/programs/gvfs-open.c b/programs/gvfs-open.c index b98d6cf..604881e 100644 --- a/programs/gvfs-open.c +++ b/programs/gvfs-open.c @@ -30,6 +30,7 @@ #include #include #include +#include static gboolean show_version = FALSE; static gchar **locations = NULL; @@ -40,6 +41,68 @@ static GOptionEntry entries[] = { {NULL} }; +static gboolean +get_bus_name_and_path_from_uri (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")) + return FALSE; + + 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 main (int argc, char *argv[]) { @@ -104,6 +167,8 @@ main (int argc, char *argv[]) do { + char *uri = NULL; + res = g_app_info_launch_default_for_uri (locations[i], NULL, &error); @@ -113,7 +178,8 @@ main (int argc, char *argv[]) /* g_app_info_launch_default_for_uri() can't properly handle non-URI (local) locations */ g_clear_error (&error); file = g_file_new_for_commandline_arg (locations[i]); - res = g_app_info_launch_default_for_uri (g_file_get_uri (file), + uri = g_file_get_uri (file); + res = g_app_info_launch_default_for_uri (uri, NULL, &error); g_object_unref (file); @@ -128,6 +194,35 @@ main (int argc, char *argv[]) g_clear_error (&error); success = FALSE; } + + /* FIXME: This chunk of madness is a workaround for a dbus-daemon bug. + * See https://bugzilla.gnome.org/show_bug.cgi?id=746534 + */ + if (res) + { + char *bus_name = NULL; + char *object_path = NULL; + + if (get_bus_name_and_path_from_uri (uri ? uri : locations[i], &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_free (uri); } while (locations[++i] != NULL); -- 2.4.3