diff options
Diffstat (limited to 'src/portal-impl.c')
-rw-r--r-- | src/portal-impl.c | 240 |
1 files changed, 152 insertions, 88 deletions
diff --git a/src/portal-impl.c b/src/portal-impl.c index 171bdbf..b67522a 100644 --- a/src/portal-impl.c +++ b/src/portal-impl.c @@ -37,9 +37,9 @@ typedef struct _PortalInterface { typedef struct _PortalConfig { char *source; - PortalInterface **ifaces; + PortalInterface **interfaces; size_t n_ifaces; - PortalInterface *dfl_portal; + PortalInterface *default_portal; } PortalConfig; static void @@ -57,10 +57,10 @@ portal_config_free (PortalConfig *config) g_clear_pointer (&config->source, g_free); for (size_t i = 0; i < config->n_ifaces; i++) - portal_interface_free (config->ifaces[i]); + portal_interface_free (config->interfaces[i]); - g_clear_pointer (&config->dfl_portal, portal_interface_free); - g_clear_pointer (&config->ifaces, g_free); + g_clear_pointer (&config->default_portal, portal_interface_free); + g_clear_pointer (&config->interfaces, g_free); g_free (config); } @@ -109,8 +109,8 @@ validate_xdg_desktop (const char *desktop) static char ** get_valid_current_desktops (const char *value) { - char **tmp; GPtrArray *valid_desktops; + char **tmp; if (value == NULL) value = g_getenv ("XDG_CURRENT_DESKTOP"); @@ -168,8 +168,8 @@ register_portal (const char *path, gboolean opt_verbose, GError **error) { - g_autoptr(GKeyFile) keyfile = g_key_file_new (); g_autoptr(PortalImplementation) impl = g_new0 (PortalImplementation, 1); + g_autoptr(GKeyFile) keyfile = g_key_file_new (); g_autofree char *basename = NULL; int i; @@ -216,15 +216,6 @@ register_portal (const char *path, } impl->use_in = g_key_file_get_string_list (keyfile, "portal", "UseIn", NULL, error); - if (opt_verbose && impl->use_in != NULL) - { - g_autofree char *uses = g_strjoinv (", ", impl->use_in); - g_warning ("Portal %s uses the deprecated UseIn key; the preferred method to " - "match portal implementations to desktop environments is to use the " - "portals.conf configuration file", - uses); - } - implementations = g_list_prepend (implementations, impl); impl = NULL; @@ -278,9 +269,9 @@ sort_impl_by_use_in_and_name (gconstpointer a, void load_installed_portals (gboolean opt_verbose) { - const char *portal_dir; - g_autoptr(GFile) dir = NULL; g_autoptr(GFileEnumerator) enumerator = NULL; + g_autoptr(GFile) dir = NULL; + const char *portal_dir; /* We need to override this in the tests */ portal_dir = g_getenv ("XDG_DESKTOP_PORTAL_DIR"); @@ -297,11 +288,13 @@ load_installed_portals (gboolean opt_verbose) while (TRUE) { - g_autoptr(GFileInfo) info = g_file_enumerator_next_file (enumerator, NULL, NULL); + g_autoptr(GFileInfo) info = NULL; + g_autoptr(GError) error = NULL; g_autoptr(GFile) child = NULL; g_autofree char *path = NULL; const char *name; - g_autoptr(GError) error = NULL; + + info = g_file_enumerator_next_file (enumerator, NULL, NULL); if (info == NULL) break; @@ -329,20 +322,27 @@ load_portal_configuration_for_dir (gboolean opt_verbose, const char *base_directory, const char *portal_file) { - g_autofree char *path = g_build_filename (base_directory, portal_file, NULL); - g_autoptr(GKeyFile) key_file = g_key_file_new (); + g_autoptr(GKeyFile) key_file = NULL; + g_autofree char *path = NULL; + g_auto(GStrv) ifaces = NULL; + + key_file = g_key_file_new (); + path = g_build_filename (base_directory, portal_file, NULL); g_debug ("Looking for portals configuration in '%s'", path); if (!g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, NULL)) return NULL; - g_auto(GStrv) ifaces = g_key_file_get_keys (key_file, "preferred", NULL, NULL); + ifaces = g_key_file_get_keys (key_file, "preferred", NULL, NULL); if (ifaces != NULL) { - g_autoptr(GPtrArray) interfaces = g_ptr_array_new_full (g_strv_length (ifaces) + 1, NULL); - g_autoptr(PortalConfig) conf = g_new0 (PortalConfig, 1); - g_autoptr(PortalInterface) dfl_portal = NULL; + g_autoptr(PortalInterface) default_portal = NULL; + g_autoptr(PortalConfig) portal_config = NULL; + g_autoptr(GPtrArray) interfaces = NULL; + + portal_config = g_new0 (PortalConfig, 1); + interfaces = g_ptr_array_new_full (g_strv_length (ifaces) + 1, NULL); for (size_t i = 0; ifaces[i] != NULL; i++) { @@ -363,76 +363,129 @@ load_portal_configuration_for_dir (gboolean opt_verbose, } if (strcmp (ifaces[i], "default") == 0) - dfl_portal = g_steal_pointer (&interface); + default_portal = g_steal_pointer (&interface); else g_ptr_array_add (interfaces, g_steal_pointer (&interface)); } - conf->n_ifaces = interfaces->len; - conf->ifaces = (PortalInterface **) g_ptr_array_steal (interfaces, NULL); - conf->dfl_portal = g_steal_pointer (&dfl_portal); + portal_config->n_ifaces = interfaces->len; + portal_config->interfaces = (PortalInterface **) g_ptr_array_steal (interfaces, NULL); + portal_config->default_portal = g_steal_pointer (&default_portal); - return g_steal_pointer (&conf); + return g_steal_pointer (&portal_config); } return NULL; } +/* + * Returns: %TRUE if configuration was found in @dir + */ +static gboolean +load_config_directory (const char *dir, + const char **desktops, + gboolean opt_verbose) +{ + g_autoptr(PortalConfig) conf = NULL; + + for (size_t i = 0; desktops[i] != NULL; i++) + { + g_autofree char *portals_conf = g_strdup_printf ("%s-portals.conf", desktops[i]); + + conf = load_portal_configuration_for_dir (opt_verbose, dir, portals_conf); + + if (conf != NULL) + { + if (opt_verbose) + g_debug ("Using portal configuration file '%s/%s' for desktop '%s'", + dir, portals_conf, desktops[i]); + + config = g_steal_pointer (&conf); + return TRUE; + } + } + + conf = load_portal_configuration_for_dir (opt_verbose, dir, "portals.conf"); + + if (conf != NULL) + { + if (opt_verbose) + g_debug ("Using portal configuration file '%s/%s' for non-specific desktop", + dir, "portals.conf"); + + config = g_steal_pointer (&conf); + return TRUE; + } + + return FALSE; +} + +#define XDP_SUBDIR "xdg-desktop-portal" + void load_portal_configuration (gboolean opt_verbose) { - g_autoptr(PortalConfig) conf = NULL; g_autofree char *user_portal_dir = NULL; + const char * const *dirs; + const char * const *iter; const char **desktops; const char *portal_dir; + desktops = get_current_lowercase_desktops (); + /* We need to override this in the tests */ portal_dir = g_getenv ("XDG_DESKTOP_PORTAL_DIR"); - if (portal_dir == NULL) - portal_dir = SYSCONFDIR "/xdg-desktop-portal"; - user_portal_dir = g_build_filename (g_get_user_config_dir (), - "xdg-desktop-portal", - NULL); + if (portal_dir != NULL) + { + load_config_directory (portal_dir, desktops, opt_verbose); + /* All other config directories are ignored when this is set */ + return; + } + + /* $XDG_CONFIG_HOME/xdg-desktop-portal/(DESKTOP-)portals.conf */ + user_portal_dir = g_build_filename (g_get_user_config_dir (), XDP_SUBDIR, NULL); - conf = load_portal_configuration_for_dir (opt_verbose, user_portal_dir, "portals.conf"); - if (conf != NULL) + if (load_config_directory (user_portal_dir, desktops, opt_verbose)) + return; + + /* $XDG_CONFIG_DIRS/xdg-desktop-portal/(DESKTOP-)portals.conf */ + dirs = g_get_system_config_dirs (); + + for (iter = dirs; iter != NULL && *iter != NULL; iter++) { - if (opt_verbose) - g_debug ("Using user portal configuration file"); + g_autofree char *dir = g_build_filename (*iter, XDP_SUBDIR, NULL); - config = g_steal_pointer (&conf); + if (load_config_directory (dir, desktops, opt_verbose)) + return; } - desktops = get_current_lowercase_desktops (); - for (size_t i = 0; desktops[i] != NULL; i++) - { - g_autofree char *portals_conf = g_strdup_printf ("%s-portals.conf", desktops[i]); + /* ${sysconfdir}/xdg-desktop-portal/(DESKTOP-)portals.conf */ + if (load_config_directory (SYSCONFDIR "/" XDP_SUBDIR, desktops, opt_verbose)) + return; - conf = load_portal_configuration_for_dir (opt_verbose, user_portal_dir, portals_conf); - if (conf != NULL) - { - if (opt_verbose) - g_debug ("Using user portal configuration file '%s' for desktop '%s'", - portals_conf, - desktops[i]); + /* $XDG_DATA_HOME/xdg-desktop-portal/(DESKTOP-)portals.conf + * (just for consistency with other XDG specifications) */ + g_clear_pointer (&user_portal_dir, g_free); + user_portal_dir = g_build_filename (g_get_user_data_dir (), XDP_SUBDIR, NULL); - config = g_steal_pointer (&conf); - return; - } + if (load_config_directory (user_portal_dir, desktops, opt_verbose)) + return; - conf = load_portal_configuration_for_dir (opt_verbose, portal_dir, portals_conf); - if (conf != NULL) - { - if (opt_verbose) - g_debug ("Using system portal configuration file '%s' for desktop '%s'", - portals_conf, - desktops[i]); + /* $XDG_DATA_DIRS/xdg-desktop-portal/(DESKTOP-)portals.conf */ + dirs = g_get_system_data_dirs (); - config = g_steal_pointer (&conf); - return; - } + for (iter = dirs; iter != NULL && *iter != NULL; iter++) + { + g_autofree char *dir = g_build_filename (*iter, XDP_SUBDIR, NULL); + + if (load_config_directory (dir, desktops, opt_verbose)) + return; } + + /* ${datadir}/xdg-desktop-portal/(DESKTOP-)portals.conf */ + if (load_config_directory (DATADIR "/" XDP_SUBDIR, desktops, opt_verbose)) + return; } static gboolean @@ -475,14 +528,14 @@ portal_impl_matches_config (const PortalImplementation *impl, */ for (int i = 0; i < config->n_ifaces; i++) { - const PortalInterface *iface = config->ifaces[i]; + const PortalInterface *iface = config->interfaces[i]; if (g_strcmp0 (iface->dbus_name, interface) == 0) return portal_impl_name_matches (impl, iface); } - if (config->dfl_portal) - return portal_impl_name_matches (impl, config->dfl_portal); + if (config->default_portal) + return portal_impl_name_matches (impl, config->default_portal); return FALSE; } @@ -494,25 +547,22 @@ find_portal_implementation (const char *interface) GList *l; int i; - desktops = get_current_lowercase_desktops (); - - for (i = 0; desktops[i] != NULL; i++) + for (l = implementations; l != NULL; l = l->next) { - for (l = implementations; l != NULL; l = l->next) - { - PortalImplementation *impl = l->data; + PortalImplementation *impl = l->data; - if (!g_strv_contains ((const char **)impl->interfaces, interface)) - continue; + if (!g_strv_contains ((const char **)impl->interfaces, interface)) + continue; - if (portal_impl_matches_config (impl, interface)) - { - g_debug ("Using %s.portal for %s in %s (config)", impl->source, interface, desktops[i]); - return impl; - } + if (portal_impl_matches_config (impl, interface)) + { + g_debug ("Using %s.portal for %s (config)", impl->source, interface); + return impl; } } + desktops = get_current_lowercase_desktops (); + /* Fallback to the old UseIn key */ for (i = 0; desktops[i] != NULL; i++) { @@ -525,25 +575,36 @@ find_portal_implementation (const char *interface) if (impl->use_in != NULL && g_strv_case_contains ((const char **)impl->use_in, desktops[i])) { + g_warning ("Choosing %s.portal for %s via the deprecated UseIn key", + impl->source, interface); + g_warning_once ("The preferred method to match portal implementations " + "to desktop environments is to use the portals.conf(5) " + "configuration file"); + g_debug ("Using %s.portal for %s in %s (fallback)", impl->source, interface, desktops[i]); return impl; } } } -#if 0 - /* Fall back to *any* installed implementation */ for (l = implementations; l != NULL; l = l->next) { PortalImplementation *impl = l->data; + if (!g_str_equal (impl->dbus_name, "org.freedesktop.impl.portal.desktop.gtk")) + continue; + if (!g_strv_contains ((const char **)impl->interfaces, interface)) continue; - g_debug ("Falling back to %s.portal for %s", impl->source, interface); + g_warning ("Choosing %s.portal for %s via temporary hard-coded fallback", + impl->source, interface); + g_warning_once ("The preferred method to match portal implementations " + "to desktop environments is to use the portals.conf(5) " + "configuration file"); + return impl; } -#endif return NULL; } @@ -560,9 +621,12 @@ find_all_portal_implementations (const char *interface) { PortalImplementation *impl = l->data; - if (g_strv_contains ((const char **)impl->interfaces, interface)) + if (!g_strv_contains ((const char **)impl->interfaces, interface)) + continue; + + if (portal_impl_matches_config (impl, interface)) { - g_debug ("Using %s.portal for %s", impl->source, interface); + g_debug ("Using %s.portal for %s (config)", impl->source, interface); g_ptr_array_add (impls, impl); } } |