mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-10-31 00:12:19 +01:00 
			
		
		
		
	gio/gdesktopappinfo: Also use document portal for desktop file snaps
When a snap is launched from its non-dbus-activable desktop file we may still need to use the portal to pass the URIs to the program, so that it can access to them even if confined. In fact most snaps are not dbus-activable, but they rely on the classic desktop file activation.
This commit is contained in:
		| @@ -2951,6 +2951,7 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info, | ||||
|   gboolean completed = FALSE; | ||||
|   GList *old_uris; | ||||
|   GList *dup_uris; | ||||
|   GList *ruris = NULL; | ||||
|  | ||||
|   char **argv, **envp; | ||||
|   int argc; | ||||
| @@ -2964,6 +2965,30 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info, | ||||
|   else | ||||
|     envp = g_get_environ (); | ||||
|  | ||||
| #ifdef G_OS_UNIX | ||||
|   if (uris && info->keyfile) | ||||
|     { | ||||
|       char *snap_instance; | ||||
|       char *app_id = NULL; | ||||
|  | ||||
|       snap_instance = g_desktop_app_info_get_string (info, "X-SnapInstanceName"); | ||||
|  | ||||
|       if (snap_instance && *snap_instance) | ||||
|         app_id = g_strconcat ("snap.", snap_instance, NULL); | ||||
|  | ||||
|       g_free (snap_instance); | ||||
|  | ||||
|       if (app_id) | ||||
|         { | ||||
|           ruris = g_document_portal_add_documents (uris, app_id, NULL); | ||||
|           if (ruris != NULL) | ||||
|             uris = ruris; | ||||
|         } | ||||
|  | ||||
|       g_clear_pointer (&app_id, g_free); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|   /* The GList* passed to expand_application_parameters() will be modified | ||||
|    * internally by expand_macro(), so we need to pass a copy of it instead, | ||||
|    * and also use that copy to control the exit condition of the loop below. | ||||
| @@ -3153,6 +3178,7 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info, | ||||
|  out: | ||||
|   g_strfreev (argv); | ||||
|   g_strfreev (envp); | ||||
|   g_list_free_full (ruris, g_free); | ||||
|  | ||||
|   return completed; | ||||
| } | ||||
|   | ||||
| @@ -33,6 +33,9 @@ | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
|  | ||||
| #include "fake-document-portal.h" | ||||
| #include "gdbus-sessionbus.h" | ||||
|  | ||||
| G_DECLARE_FINAL_TYPE (TestLaunchContext, test_launch_context, TEST, | ||||
|                       LAUNCH_CONTEXT, GAppLaunchContext); | ||||
|  | ||||
| @@ -1432,6 +1435,76 @@ test_default_uri_handler_async (void) | ||||
|   g_free (file_path); | ||||
| } | ||||
|  | ||||
| static void | ||||
| launch_snap_uris_with_portal (void) | ||||
| { | ||||
|   GDesktopAppInfo *appinfo; | ||||
|   GError *error = NULL; | ||||
|   gboolean retval; | ||||
|   const gchar *path; | ||||
|   const gchar *path2; | ||||
|   gboolean invoked = FALSE; | ||||
|   gboolean launched = FALSE; | ||||
|   gboolean failed = FALSE; | ||||
|   gboolean child_waited = FALSE; | ||||
|   GAppLaunchContext *context; | ||||
|   GList *uris = NULL; | ||||
|   GFakeDocumentPortalThread *thread = NULL; | ||||
|  | ||||
|   /* Run a fake-document-portal */ | ||||
|   session_bus_up (); | ||||
|   thread = g_fake_document_portal_thread_new (session_bus_get_address (), | ||||
|                                               "snap.snap-app"); | ||||
|   g_fake_document_portal_thread_run (thread); | ||||
|  | ||||
|   path = g_test_get_filename (G_TEST_BUILT, "snap-app_appinfo-test.desktop", NULL); | ||||
|   appinfo = g_desktop_app_info_new_from_filename (path); | ||||
|   g_assert_true (G_IS_APP_INFO (appinfo)); | ||||
|  | ||||
|   path2 = g_test_get_filename (G_TEST_BUILT, "appinfo-test.desktop", NULL); | ||||
|   g_assert_true (g_file_test (path2, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)); | ||||
|  | ||||
|   context = g_object_new (test_launch_context_get_type (), NULL); | ||||
|   g_signal_connect (context, "launch-started", | ||||
|                     G_CALLBACK (on_launch_started), | ||||
|                     &invoked); | ||||
|   g_signal_connect (context, "launched", | ||||
|                     G_CALLBACK (on_launched), | ||||
|                     &launched); | ||||
|   g_signal_connect (context, "launch-failed", | ||||
|                     G_CALLBACK (on_launch_failed), | ||||
|                     &failed); | ||||
|   g_app_launch_context_setenv (context, "DOCUMENT_PORTAL_MOUNT_POINT", | ||||
|                                g_fake_document_portal_thread_get_mount_point (thread)); | ||||
|  | ||||
|   uris = g_list_append (uris, g_strconcat ("file://", path, NULL)); | ||||
|   uris = g_list_append (uris, g_strconcat ("file://", path2, NULL)); | ||||
|  | ||||
|   retval = g_desktop_app_info_launch_uris_as_manager (appinfo, uris, | ||||
|                                                       context, | ||||
|                                                       G_SPAWN_DO_NOT_REAP_CHILD, | ||||
|                                                       NULL, | ||||
|                                                       NULL, | ||||
|                                                       wait_child_completed, | ||||
|                                                       &child_waited, | ||||
|                                                       &error); | ||||
|  | ||||
|   g_assert_no_error (error); | ||||
|   g_assert_true (retval); | ||||
|   g_assert_true (invoked); | ||||
|   g_assert_true (launched); | ||||
|   g_assert_true (child_waited); | ||||
|   g_assert_false (failed); | ||||
|  | ||||
|   g_clear_list (&uris, g_free); | ||||
|   g_object_unref (appinfo); | ||||
|   g_assert_finalize_object (context); | ||||
|  | ||||
|   g_fake_document_portal_thread_stop (thread); | ||||
|   g_clear_object (&thread); | ||||
|   session_bus_down (); | ||||
| } | ||||
|  | ||||
| /* Test if Desktop-File Id is correctly formed */ | ||||
| static void | ||||
| test_id (void) | ||||
| @@ -2062,6 +2135,7 @@ main (int   argc, | ||||
|   g_test_add_func ("/desktop-app-info/launch-as-manager/fail", test_launch_as_manager_fail); | ||||
|   g_test_add_func ("/desktop-app-info/launch-default-uri-handler", test_default_uri_handler); | ||||
|   g_test_add_func ("/desktop-app-info/launch-default-uri-handler-async", test_default_uri_handler_async); | ||||
|   g_test_add_func ("/desktop-app-info/launch-snap-uri-with-portal", launch_snap_uris_with_portal); | ||||
|   g_test_add_func ("/desktop-app-info/id", test_id); | ||||
|  | ||||
|   for (i = 0; i < G_N_ELEMENTS (supported_terminals); i++) | ||||
|   | ||||
| @@ -370,13 +370,6 @@ if host_machine.system() != 'windows' | ||||
|         'install' : false, | ||||
|         'extra_programs' : ['appinfo-test'], | ||||
|       }, | ||||
|       'desktop-app-info' : { | ||||
|         'install' : false, | ||||
|         'depends' : gio_launch_desktop, | ||||
|         'extra_programs' : ['apps', 'appinfo-test'], | ||||
|         # FIXME: https://gitlab.gnome.org/GNOME/glib/-/issues/3148 | ||||
|         'can_fail' : host_system == 'gnu', | ||||
|       }, | ||||
|     } | ||||
|   endif | ||||
|  | ||||
| @@ -384,6 +377,7 @@ if host_machine.system() != 'windows' | ||||
|     'basic-application' : {}, | ||||
|     'dbus-launch' : {}, | ||||
|     'appinfo-test' : {}, | ||||
|     'snapinfo-test' : {}, | ||||
|   } | ||||
|  | ||||
|   if not glib_have_cocoa | ||||
| @@ -622,6 +616,14 @@ if host_machine.system() != 'windows' | ||||
|         'dbus-appinfo' : { | ||||
|           'extra_sources' : [extra_sources, fake_document_portal_sources], | ||||
|         }, | ||||
|         'desktop-app-info' : { | ||||
|           'install' : false, | ||||
|           'depends' : gio_launch_desktop, | ||||
|           'extra_programs' : ['apps', 'appinfo-test', 'snapinfo-test'], | ||||
|           # FIXME: https://gitlab.gnome.org/GNOME/glib/-/issues/3148 | ||||
|           'can_fail' : host_system == 'gnu', | ||||
|           'extra_sources' : [extra_sources, fake_document_portal_sources], | ||||
|         }, | ||||
|       } | ||||
|     endif | ||||
|  | ||||
| @@ -750,6 +752,7 @@ appinfo_test_desktop_files = [ | ||||
|   'appinfo-test-path', | ||||
|   'appinfo-test', | ||||
|   'appinfo-test2', | ||||
|   'snap-app_appinfo-test', | ||||
| ] | ||||
|  | ||||
| foreach appinfo_test_desktop_file : appinfo_test_desktop_files | ||||
|   | ||||
							
								
								
									
										12
									
								
								gio/tests/snap-app_appinfo-test.desktop.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								gio/tests/snap-app_appinfo-test.desktop.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| # SPDX-License-Identifier: CC0-1.0 | ||||
| # SPDX-FileCopyrightText: 2025 Marco Trevisan (Treviño) | ||||
| [Desktop Entry] | ||||
| Type=Application | ||||
| Version=1.0 | ||||
| Name=Snap Test | ||||
| X-SnapInstanceName=snap-app | ||||
| X-SnapAppName=appinfo-test | ||||
| X-SnapCommonID=org.gio.snap-app.appinfo-test | ||||
| DBusActivatable=false | ||||
| Exec=@installed_tests_dir@/snapinfo-test %U | ||||
| StartupNotify=true | ||||
							
								
								
									
										51
									
								
								gio/tests/snapinfo-test.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								gio/tests/snapinfo-test.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| /** | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  * SPDX-FileCopyrightText: 2025 Marco Trevisan (Treviño) | ||||
|  */ | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <gio/gio.h> | ||||
|  | ||||
| int | ||||
| main (int argc, char *argv[]) | ||||
| { | ||||
|   const char *envvar; | ||||
|   const char *document_portal_mount; | ||||
|   char *expected; | ||||
|   char *expected_files[3] = {0}; | ||||
|   gint pid_from_env; | ||||
|  | ||||
|   g_test_init (&argc, &argv, NULL); | ||||
|  | ||||
|   envvar = g_getenv ("GIO_LAUNCHED_DESKTOP_FILE"); | ||||
|   g_assert_nonnull (envvar); | ||||
|  | ||||
|   expected = g_test_build_filename (G_TEST_BUILT, "snap-app_appinfo-test.desktop", NULL); | ||||
|   g_assert_cmpstr (envvar, ==, expected); | ||||
|   g_free (expected); | ||||
|  | ||||
|   envvar = g_getenv ("GIO_LAUNCHED_DESKTOP_FILE_PID"); | ||||
|   g_assert (envvar != NULL); | ||||
|   pid_from_env = atoi (envvar); | ||||
|   g_assert_cmpint (pid_from_env, ==, getpid ()); | ||||
|  | ||||
|   document_portal_mount = g_getenv ("DOCUMENT_PORTAL_MOUNT_POINT"); | ||||
|   g_assert_nonnull (document_portal_mount); | ||||
|  | ||||
|   expected_files[0] = g_build_filename (document_portal_mount, | ||||
|                                         "document-id-0", "snap-app_appinfo-test.desktop", | ||||
|                                         NULL); | ||||
|   expected_files[1] = g_build_filename (document_portal_mount, | ||||
|                                         "document-id-1", "appinfo-test.desktop", | ||||
|                                         NULL); | ||||
|  | ||||
|   g_assert_cmpint (argc, ==, 3); | ||||
|  | ||||
|   for (size_t i = 0; i < G_N_ELEMENTS (expected_files); ++i) | ||||
|     { | ||||
|       g_assert_cmpstr (argv[i+1], ==, expected_files[i]); | ||||
|       g_clear_pointer (&expected_files[i], g_free); | ||||
|     } | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user