[gnome-builder] flatpak: connect system/user fonts when running application



commit 6e98bb98d72dadd34aec1665f4daebc989c56ce4
Author: Christian Hergert <chergert redhat com>
Date:   Wed Sep 8 15:42:16 2021 -0700

    flatpak: connect system/user fonts when running application
    
    When running Flatpak applications, we are using 'flatpak build' since the
    application has not yet been commited to an OSTree repository. That means
    we do not get help from the system for things like "flatpak run" where
    font caches would be wired into the process.
    
    This attempts to alleviate that by manually doing the work that flatpak-run
    does. It's not exact, and in particular we might risk writing to font
    caches, but that appears to be okay.
    
    Long term, we probably want to address this in:
    
      https://github.com/flatpak/flatpak/issues/4404
    
    Fixes #1519

 src/plugins/flatpak/flatpak-plugin.c     |   3 +
 src/plugins/flatpak/gbp-flatpak-aux.c    | 174 +++++++++++++++++++++++++++++++
 src/plugins/flatpak/gbp-flatpak-aux.h    |  31 ++++++
 src/plugins/flatpak/gbp-flatpak-runner.c |   3 +
 src/plugins/flatpak/meson.build          |   1 +
 5 files changed, 212 insertions(+)
---
diff --git a/src/plugins/flatpak/flatpak-plugin.c b/src/plugins/flatpak/flatpak-plugin.c
index 120e1365f..91f06d28e 100644
--- a/src/plugins/flatpak/flatpak-plugin.c
+++ b/src/plugins/flatpak/flatpak-plugin.c
@@ -27,6 +27,7 @@
 #include <libide-foundry.h>
 #include <libide-gui.h>
 
+#include "gbp-flatpak-aux.h"
 #include "gbp-flatpak-build-system-discovery.h"
 #include "gbp-flatpak-build-target-provider.h"
 #include "gbp-flatpak-config-provider.h"
@@ -57,4 +58,6 @@ _gbp_flatpak_register_types (PeasObjectModule *module)
   peas_object_module_register_extension_type (module,
                                               IDE_TYPE_PIPELINE_ADDIN,
                                               GBP_TYPE_FLATPAK_PIPELINE_ADDIN);
+
+  gbp_flatpak_aux_init ();
 }
diff --git a/src/plugins/flatpak/gbp-flatpak-aux.c b/src/plugins/flatpak/gbp-flatpak-aux.c
new file mode 100644
index 000000000..b6a250729
--- /dev/null
+++ b/src/plugins/flatpak/gbp-flatpak-aux.c
@@ -0,0 +1,174 @@
+/* gbp-flatpak-aux.c
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#include "gbp-flatpak-aux.h"
+
+#define SYSTEM_FONTS_DIR       "/usr/share/fonts"
+#define SYSTEM_FONT_CACHE_DIRS "/var/cache/fontconfig:/usr/lib/fontconfig/cache"
+
+/* The goal of this file is to help us setup things that might be
+ * needed for applications to look/work right even though they are
+ * not installed. For example, we need to setup font remaps for
+ * applications since "flatpak build" will not do that for us.
+ */
+
+static GFile *local;
+static GFile *mapped;
+static GPtrArray *maps;
+static gboolean initialized;
+
+void
+gbp_flatpak_aux_init (void)
+{
+  g_autoptr(GString) xml_snippet = g_string_new ("");
+  g_auto(GStrv) system_cache_dirs = NULL;
+  g_autoptr(GFile) user1 = NULL;
+  g_autoptr(GFile) user2 = NULL;
+  g_autoptr(GFile) user_cache = NULL;
+  g_autofree char *cache_dir = NULL;
+  g_autofree char *data_dir = NULL;
+  guint i;
+
+  if (initialized)
+    return;
+
+  initialized = TRUE;
+
+  /* It would be nice if we had a way to get XDG dirs from the host
+   * system when we need to break out of flatpak to run flatpak bits
+   * through the system.
+   */
+
+  if (ide_is_flatpak ())
+    {
+      cache_dir = g_build_filename (g_get_home_dir (), ".cache", NULL);
+      data_dir = g_build_filename (g_get_home_dir (), ".local", "share", NULL);
+    }
+  else
+    {
+      cache_dir = g_strdup (g_get_user_cache_dir ());
+      data_dir = g_strdup (g_get_user_data_dir ());
+    }
+
+  local = g_file_new_for_path ("/run/host/font-dirs.xml");
+  mapped = g_file_new_build_filename (cache_dir, "font-dirs.xml", NULL);
+  maps = g_ptr_array_new ();
+
+  g_string_append (xml_snippet,
+                   "<?xml version=\"1.0\"?>\n"
+                   "<!DOCTYPE fontconfig SYSTEM \"fonts.dtd\">\n"
+                   "<fontconfig>\n");
+
+  if (g_file_test (SYSTEM_FONTS_DIR, G_FILE_TEST_EXISTS))
+    {
+      /* TODO: How can we *force* this read-only? */
+      g_ptr_array_add (maps, g_strdup ("--bind-mount=/run/host/fonts=" SYSTEM_FONTS_DIR));
+      g_string_append_printf (xml_snippet,
+                              "\t<remap-dir as-path=\"%s\">/run/host/fonts</remap-dir>\n",
+                              SYSTEM_FONTS_DIR);
+    }
+
+  if (g_file_test ("/usr/local/share/fonts", G_FILE_TEST_EXISTS))
+    {
+      /* TODO: How can we *force* this read-only? */
+      g_ptr_array_add (maps, g_strdup ("--bind-mount=/run/host/local-fonts=/usr/local/share/fonts"));
+      g_string_append_printf (xml_snippet,
+                              "\t<remap-dir as-path=\"%s\">/run/host/local-fonts</remap-dir>\n",
+                              "/usr/local/share/fonts");
+    }
+
+  system_cache_dirs = g_strsplit (SYSTEM_FONT_CACHE_DIRS, ":", 0);
+  for (i = 0; system_cache_dirs[i] != NULL; i++)
+    {
+      if (g_file_test (system_cache_dirs[i], G_FILE_TEST_EXISTS))
+        {
+          /* TODO: How can we *force* this read-only? */
+          g_ptr_array_add (maps,
+                           g_strdup_printf ("--bind-mount=/run/host/fonts-cache=%s",
+                                            system_cache_dirs[i]));
+          break;
+        }
+    }
+
+  user1 = g_file_new_build_filename (data_dir, "fonts", NULL);
+  user2 = g_file_new_build_filename (g_get_home_dir (), ".fonts", NULL);
+  user_cache = g_file_new_build_filename (cache_dir, "fontconfig", NULL);
+
+  if (g_file_query_exists (user1, NULL))
+    {
+      g_ptr_array_add (maps, g_strdup_printf ("--filesystem=%s:ro", g_file_peek_path (user1)));
+      g_string_append_printf (xml_snippet,
+                              "\t<remap-dir as-path=\"%s\">/run/host/user-fonts</remap-dir>\n",
+                              g_file_peek_path (user1));
+
+    }
+  else if (g_file_query_exists (user2, NULL))
+    {
+      g_ptr_array_add (maps, g_strdup_printf ("--filesystem=%s:ro", g_file_peek_path (user2)));
+      g_string_append_printf (xml_snippet,
+                              "\t<remap-dir as-path=\"%s\">/run/host/user-fonts</remap-dir>\n",
+                              g_file_peek_path (user2));
+    }
+
+  if (g_file_query_exists (user_cache, NULL))
+    {
+      g_ptr_array_add (maps, g_strdup_printf ("--filesystem=%s:ro", g_file_peek_path (user_cache)));
+      g_ptr_array_add (maps, g_strdup_printf ("--bind-mount=/run/host/user-fonts-cache=%s",
+                                              g_file_peek_path (user_cache)));
+    }
+
+  g_string_append (xml_snippet, "</fontconfig>\n");
+
+  g_file_replace_contents (mapped, xml_snippet->str, xml_snippet->len,
+                           NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION,
+                           NULL, NULL, NULL);
+
+  g_ptr_array_add (maps,
+                   g_strdup_printf ("--bind-mount=/run/host/font-dirs.xml=%s",
+                                    g_file_peek_path (mapped)));
+}
+
+int
+gbp_flatpak_aux_apply (IdeSubprocessLauncher *launcher,
+                       int                    position)
+{
+  static const char *arg;
+  int count = 0;
+
+  g_return_val_if_fail (IDE_IS_SUBPROCESS_LAUNCHER (launcher), 0);
+  g_return_val_if_fail (initialized, 0);
+
+  if (arg == NULL)
+    arg = g_strdup_printf ("--bind-mount=/run/host/font-dirs.xml=%s",
+                           g_file_peek_path (mapped));
+
+  for (guint i = 0; i < maps->len; i++)
+    {
+      ide_subprocess_launcher_insert_argv (launcher, position++, (const char *)g_ptr_array_index (maps, i));
+      count++;
+    }
+
+  ide_subprocess_launcher_insert_argv (launcher, position++, arg);
+  count++;
+
+  return count;
+}
diff --git a/src/plugins/flatpak/gbp-flatpak-aux.h b/src/plugins/flatpak/gbp-flatpak-aux.h
new file mode 100644
index 000000000..6c01a35d4
--- /dev/null
+++ b/src/plugins/flatpak/gbp-flatpak-aux.h
@@ -0,0 +1,31 @@
+/* gbp-flatpak-aux.h
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-threading.h>
+
+G_BEGIN_DECLS
+
+void gbp_flatpak_aux_init  (void);
+int  gbp_flatpak_aux_apply (IdeSubprocessLauncher *launcher,
+                            int                    position);
+
+G_END_DECLS
diff --git a/src/plugins/flatpak/gbp-flatpak-runner.c b/src/plugins/flatpak/gbp-flatpak-runner.c
index 58a38d406..e097aa984 100644
--- a/src/plugins/flatpak/gbp-flatpak-runner.c
+++ b/src/plugins/flatpak/gbp-flatpak-runner.c
@@ -25,6 +25,7 @@
 #include <glib/gi18n.h>
 #include <unistd.h>
 
+#include "gbp-flatpak-aux.h"
 #include "gbp-flatpak-manifest.h"
 #include "gbp-flatpak-runner.h"
 #include "gbp-flatpak-util.h"
@@ -109,6 +110,8 @@ gbp_flatpak_runner_fixup_launcher (IdeRunner             *runner,
   ide_subprocess_launcher_insert_argv (launcher, i++, "--allow=devel");
   ide_subprocess_launcher_insert_argv (launcher, i++, doc_portal);
 
+  i += gbp_flatpak_aux_apply (launcher, i);
+
   if (GBP_IS_FLATPAK_MANIFEST (config))
     {
       const gchar * const *finish_args;
diff --git a/src/plugins/flatpak/meson.build b/src/plugins/flatpak/meson.build
index 7c819702f..d6455ab0b 100644
--- a/src/plugins/flatpak/meson.build
+++ b/src/plugins/flatpak/meson.build
@@ -15,6 +15,7 @@ subdir('daemon')
 
 plugins_sources += files([
   'flatpak-plugin.c',
+  'gbp-flatpak-aux.c',
   'gbp-flatpak-build-system-discovery.c',
   'gbp-flatpak-build-target-provider.c',
   'gbp-flatpak-build-target.c',


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]