diff options
author | Ray Strode <rstrode@redhat.com> | 2015-05-20 16:25:01 -0400 |
---|---|---|
committer | Ondrej Holy <oholy@redhat.com> | 2015-06-09 12:28:08 +0200 |
commit | 9297474c33192fe210f0cbc9ffc349f19604516a (patch) | |
tree | 210181ab3228deecf7600ad788492846f108b2ab | |
parent | 676ba166c0b7c69e65bce7f1ec5e38ac36ad33c8 (diff) | |
download | gvfs-9297474c33192fe210f0cbc9ffc349f19604516a.tar.gz |
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
-rw-r--r-- | programs/gvfs-open.c | 93 |
1 files changed, 92 insertions, 1 deletions
diff --git a/programs/gvfs-open.c b/programs/gvfs-open.c index 20e5c87b..bb518dc1 100644 --- a/programs/gvfs-open.c +++ b/programs/gvfs-open.c @@ -30,6 +30,7 @@ #include <glib.h> #include <glib/gi18n.h> #include <gio/gio.h> +#include <gio/gdesktopappinfo.h> 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[]) { @@ -124,7 +187,6 @@ main (int argc, char *argv[]) res = g_app_info_launch_default_for_uri (uri ? uri : locations[i], NULL, &error); - g_free (uri); if (!res) { @@ -135,6 +197,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); |