diff --git a/data/org.freedesktop.portal.Flatpak.xml b/data/org.freedesktop.portal.Flatpak.xml index 2bf97c9c..083c6e3b 100644 --- a/data/org.freedesktop.portal.Flatpak.xml +++ b/data/org.freedesktop.portal.Flatpak.xml @@ -80,6 +80,12 @@ Spawn without network (equivalent of the unshare=network option of flatpak run). + + 16 + + Kill the sandbox when the caller disappears from the session bus. + + The following options are supported: diff --git a/portal/flatpak-portal.c b/portal/flatpak-portal.c index 401fb0e2..2b3f02b9 100644 --- a/portal/flatpak-portal.c +++ b/portal/flatpak-portal.c @@ -117,6 +117,7 @@ typedef struct GPid pid; char *client; guint child_watch; + gboolean watch_bus; } PidData; static void @@ -607,6 +608,7 @@ handle_spawn (PortalFlatpak *object, pid_data = g_new0 (PidData, 1); pid_data->pid = pid; pid_data->client = g_strdup (g_dbus_method_invocation_get_sender (invocation)); + pid_data->watch_bus = (arg_flags & FLATPAK_SPAWN_FLAGS_WATCH_BUS) != 0; pid_data->child_watch = g_child_watch_add_full (G_PRIORITY_DEFAULT, pid, child_watch_died, @@ -690,6 +692,52 @@ authorize_method_handler (GDBusInterfaceSkeleton *interface, return TRUE; } +static void +name_owner_changed (GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + const char *name, *from, *to; + + g_variant_get (parameters, "(&s&s&s)", &name, &from, &to); + + if (name[0] == ':' && + strcmp (name, from) == 0 && + strcmp (to, "") == 0) + { + GHashTableIter iter; + PidData *pid_data = NULL; + gpointer value = NULL; + GList *list = NULL, *l; + + g_hash_table_iter_init (&iter, client_pid_data_hash); + while (g_hash_table_iter_next (&iter, NULL, &value)) + { + pid_data = value; + + if (pid_data->watch_bus && g_str_equal (pid_data->client, name)) + list = g_list_prepend (list, pid_data); + } + + for (l = list; l; l = l->next) + { + pid_data = l->data; + g_debug ("%s dropped off the bus, killing %d", pid_data->client, pid_data->pid); + killpg (pid_data->pid, SIGINT); + } + + g_list_free (list); + } +} + +#define DBUS_NAME_DBUS "org.freedesktop.DBus" +#define DBUS_INTERFACE_DBUS DBUS_NAME_DBUS +#define DBUS_PATH_DBUS "/org/freedesktop/DBus" + static void on_bus_acquired (GDBusConnection *connection, const gchar *name, @@ -701,6 +749,16 @@ on_bus_acquired (GDBusConnection *connection, portal = portal_flatpak_skeleton_new (); + g_dbus_connection_signal_subscribe (connection, + DBUS_NAME_DBUS, + DBUS_INTERFACE_DBUS, + "NameOwnerChanged", + DBUS_PATH_DBUS, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + name_owner_changed, + NULL, NULL); + g_object_set_data_full (G_OBJECT (portal), "track-alive", GINT_TO_POINTER (42), skeleton_died_cb); g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (portal), diff --git a/portal/flatpak-portal.h b/portal/flatpak-portal.h index 0bc97a4a..10ac1dd8 100644 --- a/portal/flatpak-portal.h +++ b/portal/flatpak-portal.h @@ -26,11 +26,13 @@ typedef enum { FLATPAK_SPAWN_FLAGS_LATEST_VERSION = 1 << 1, FLATPAK_SPAWN_FLAGS_SANDBOX = 1 << 2, FLATPAK_SPAWN_FLAGS_NO_NETWORK = 1 << 3, + FLATPAK_SPAWN_FLAGS_WATCH_BUS = 1 << 4, } FlatpakSpawnFlags; #define FLATPAK_SPAWN_FLAGS_ALL (FLATPAK_SPAWN_FLAGS_CLEAR_ENV | \ FLATPAK_SPAWN_FLAGS_LATEST_VERSION | \ FLATPAK_SPAWN_FLAGS_SANDBOX | \ - FLATPAK_SPAWN_FLAGS_NO_NETWORK) + FLATPAK_SPAWN_FLAGS_NO_NETWORK | \ + FLATPAK_SPAWN_FLAGS_WATCH_BUS) #endif /* __FLATPAK_PORTAL_H__ */