From: Colin Walters Date: Mon, 20 Dec 2010 19:48:53 +0000 (-0500) Subject: gdesktopappinfo: Add g_desktop_app_info_launch_uris_as_manager() X-Git-Tag: 2.27.90~14 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e6546debd61d32b41b37c20b62d4e47cd3e53e25;p=platform%2Fupstream%2Fglib.git gdesktopappinfo: Add g_desktop_app_info_launch_uris_as_manager() A new GDesktopAppInfo specific function which provides more control over launched processes. Intended basically only for use in GNOME Shell, where we want: *) To directly know the GPid for each launched program, without having to listen to a DBus signal emitted in our own process *) Possibly control over the process environment; for example, we may want to call setsid() or redirect file descriptors. And in the future: *) To avoid recursively calling ourself via DBus, when a later patch causes g_app_info_launch() to indirect via the shell. https://bugzilla.gnome.org/show_bug.cgi?id=606960 --- diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c index 5851e02..00fbd9c 100644 --- a/gio/gdesktopappinfo.c +++ b/gio/gdesktopappinfo.c @@ -898,6 +898,8 @@ create_files_for_uris (GList *uris) typedef struct { + GSpawnChildSetupFunc user_setup; + gpointer user_setup_data; char *display; char *sn_id; char *desktop_file; @@ -923,6 +925,9 @@ child_setup (gpointer user_data) g_snprintf (pid, 20, "%ld", (long)getpid ()); g_setenv ("GIO_LAUNCHED_DESKTOP_FILE_PID", pid, TRUE); } + + if (data->user_setup) + data->user_setup (data->user_setup_data); } static void @@ -968,11 +973,18 @@ notify_desktop_launch (GDBusConnection *session_bus, g_object_unref (msg); } +#define _SPAWN_FLAGS_DEFAULT (G_SPAWN_SEARCH_PATH) + static gboolean -g_desktop_app_info_launch_uris (GAppInfo *appinfo, - GList *uris, - GAppLaunchContext *launch_context, - GError **error) +_g_desktop_app_info_launch_uris_internal (GAppInfo *appinfo, + GList *uris, + GAppLaunchContext *launch_context, + GSpawnFlags spawn_flags, + GSpawnChildSetupFunc user_setup, + gpointer user_setup_data, + GDesktopAppLaunchCallback pid_callback, + gpointer pid_callback_data, + GError **error) { GDesktopAppInfo *info = G_DESKTOP_APP_INFO (appinfo); GDBusConnection *session_bus; @@ -1012,6 +1024,8 @@ g_desktop_app_info_launch_uris (GAppInfo *appinfo, goto out; } + data.user_setup = user_setup; + data.user_setup_data = user_setup_data; data.display = NULL; data.sn_id = NULL; data.desktop_file = info->filename; @@ -1035,7 +1049,7 @@ g_desktop_app_info_launch_uris (GAppInfo *appinfo, if (!g_spawn_async (info->path, argv, NULL, - G_SPAWN_SEARCH_PATH, + spawn_flags, child_setup, &data, &pid, @@ -1051,6 +1065,9 @@ g_desktop_app_info_launch_uris (GAppInfo *appinfo, goto out; } + if (pid_callback != NULL) + pid_callback (info, pid, pid_callback_data); + notify_desktop_launch (session_bus, info->filename, pid, @@ -1082,6 +1099,19 @@ g_desktop_app_info_launch_uris (GAppInfo *appinfo, } static gboolean +g_desktop_app_info_launch_uris (GAppInfo *appinfo, + GList *uris, + GAppLaunchContext *launch_context, + GError **error) +{ + return _g_desktop_app_info_launch_uris_internal (appinfo, uris, + launch_context, + _SPAWN_FLAGS_DEFAULT, + NULL, NULL, NULL, NULL, + error); +} + +static gboolean g_desktop_app_info_supports_uris (GAppInfo *appinfo) { GDesktopAppInfo *info = G_DESKTOP_APP_INFO (appinfo); @@ -1129,6 +1159,55 @@ g_desktop_app_info_launch (GAppInfo *appinfo, return res; } +/** + * g_desktop_app_info_launch_uris_as_manager: + * @appinfo: a #GDesktopAppInfo + * @uris: (element-type utf8): List of URIs + * @launch_context: a #GAppLaunchContext + * @spawn_flags: #GSpawnFlags, used for each process + * @user_setup: a #GSpawnChildSetupFunc, used once for each process. + * @user_setup_data: (closure user_setup): User data for @user_setup + * @pid_callback: (scope call): Callback for child processes + * @pid_callback_data: (closure pid_callback): User data for @callback + * @error: a #GError + * + * This function performs the equivalent of g_app_info_launch_uris(), + * but is intended primarily for operating system components that + * launch applications. Ordinary applications should use + * g_app_info_launch_uris(). + * + * In contrast to g_app_info_launch_uris(), all processes created will + * always be run directly as children as if by the UNIX fork()/exec() + * calls. + * + * This guarantee allows additional control over the exact environment + * of the child processes, which is provided via a setup function + * @setup, as well as the process identifier of each child process via + * @pid_callback. See g_spawn_async() for more information about the + * semantics of the @setup function. + */ +gboolean +g_desktop_app_info_launch_uris_as_manager (GDesktopAppInfo *appinfo, + GList *uris, + GAppLaunchContext *launch_context, + GSpawnFlags spawn_flags, + GSpawnChildSetupFunc user_setup, + gpointer user_setup_data, + GDesktopAppLaunchCallback pid_callback, + gpointer pid_callback_data, + GError **error) +{ + return _g_desktop_app_info_launch_uris_internal ((GAppInfo*)appinfo, + uris, + launch_context, + spawn_flags, + user_setup, + user_setup_data, + pid_callback, + pid_callback_data, + error); +} + G_LOCK_DEFINE_STATIC (g_desktop_env); static gchar *g_desktop_env = NULL; diff --git a/gio/gdesktopappinfo.h b/gio/gdesktopappinfo.h index 6be9369..f0fc924 100644 --- a/gio/gdesktopappinfo.h +++ b/gio/gdesktopappinfo.h @@ -93,6 +93,30 @@ GType g_desktop_app_info_lookup_get_type (void) G_GNUC_CON GAppInfo *g_desktop_app_info_lookup_get_default_for_uri_scheme (GDesktopAppInfoLookup *lookup, const char *uri_scheme); +/** + * GDesktopAppLaunchCallback: + * @appinfo: a #GDesktopAppInfo + * @pid: Process identifier + * @user_data: User data + * + * During invocation, g_desktop_app_info_launch_uris_as_manager() may + * create one or more child processes. This callback is invoked once + * for each, providing the process ID. + */ +typedef void (GDesktopAppLaunchCallback) (GDesktopAppInfo *appinfo, + GPid pid, + gpointer user_data); + +gboolean g_desktop_app_info_launch_uris_as_manager (GDesktopAppInfo *appinfo, + GList *uris, + GAppLaunchContext *launch_context, + GSpawnFlags spawn_flags, + GSpawnChildSetupFunc setup, + gpointer user_setup_data, + GDesktopAppLaunchCallback callback, + gpointer pid_callback_data, + GError **error); + #endif /* G_DISABLE_DEPRECATED */ G_END_DECLS