bd1e7a
From 6edc7e0cfc672fe4c2331ac8131ea1aa82881b63 Mon Sep 17 00:00:00 2001
bd1e7a
From: Matthias Clasen <mclasen@redhat.com>
bd1e7a
Date: Wed, 19 Dec 2018 19:58:16 -0500
bd1e7a
Subject: [PATCH 1/9] settings: Make the keyfile backend parameterless
bd1e7a
bd1e7a
Make it possible to instantiate a keyfile settings backend
bd1e7a
without specifying parameters, by turning the arguments to
bd1e7a
the new() function into construct-only properties. If no
bd1e7a
filename is specified, default to
bd1e7a
$XDG_CONFIG_HOME/glib-2.0/settings/keyfile
bd1e7a
---
bd1e7a
 gio/gkeyfilesettingsbackend.c  | 252 ++++++++++++++++++++++++++-------
bd1e7a
 gio/gsettingsbackendinternal.h |   2 +
bd1e7a
 2 files changed, 199 insertions(+), 55 deletions(-)
bd1e7a
bd1e7a
diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
bd1e7a
index a37978e83..e8e9f44a5 100644
bd1e7a
--- a/gio/gkeyfilesettingsbackend.c
bd1e7a
+++ b/gio/gkeyfilesettingsbackend.c
bd1e7a
@@ -21,6 +21,9 @@
bd1e7a
 
bd1e7a
 #include "config.h"
bd1e7a
 
bd1e7a
+#include <glib.h>
bd1e7a
+#include <glibintl.h>
bd1e7a
+
bd1e7a
 #include <stdio.h>
bd1e7a
 #include <string.h>
bd1e7a
 
bd1e7a
@@ -28,7 +31,8 @@
bd1e7a
 #include "gfileinfo.h"
bd1e7a
 #include "gfilemonitor.h"
bd1e7a
 #include "gsimplepermission.h"
bd1e7a
-#include "gsettingsbackend.h"
bd1e7a
+#include "gsettingsbackendinternal.h"
bd1e7a
+#include "giomodule.h"
bd1e7a
 
bd1e7a
 
bd1e7a
 #define G_TYPE_KEYFILE_SETTINGS_BACKEND      (g_keyfile_settings_backend_get_type ())
bd1e7a
@@ -41,6 +45,12 @@
bd1e7a
 
bd1e7a
 typedef GSettingsBackendClass GKeyfileSettingsBackendClass;
bd1e7a
 
bd1e7a
+enum {
bd1e7a
+  PROP_FILENAME = 1,
bd1e7a
+  PROP_ROOT_PATH,
bd1e7a
+  PROP_ROOT_GROUP
bd1e7a
+};
bd1e7a
+
bd1e7a
 typedef struct
bd1e7a
 {
bd1e7a
   GSettingsBackend   parent_instance;
bd1e7a
@@ -61,7 +71,6 @@ typedef struct
bd1e7a
   GFileMonitor      *dir_monitor;
bd1e7a
 } GKeyfileSettingsBackend;
bd1e7a
 
bd1e7a
-static GType g_keyfile_settings_backend_get_type (void);
bd1e7a
 G_DEFINE_TYPE (GKeyfileSettingsBackend,
bd1e7a
                g_keyfile_settings_backend,
bd1e7a
                G_TYPE_SETTINGS_BACKEND)
bd1e7a
@@ -287,7 +296,8 @@ g_keyfile_settings_backend_check_one (gpointer key,
bd1e7a
 {
bd1e7a
   WriteManyData *data = user_data;
bd1e7a
 
bd1e7a
-  return data->failed = !path_is_valid (data->kfsb, key);
bd1e7a
+  return data->failed = g_hash_table_contains (data->kfsb->system_locks, key) ||
bd1e7a
+                        !path_is_valid (data->kfsb, key);
bd1e7a
 }
bd1e7a
 
bd1e7a
 static gboolean
bd1e7a
@@ -522,25 +532,6 @@ g_keyfile_settings_backend_init (GKeyfileSettingsBackend *kfsb)
bd1e7a
 {
bd1e7a
 }
bd1e7a
 
bd1e7a
-static void
bd1e7a
-g_keyfile_settings_backend_class_init (GKeyfileSettingsBackendClass *class)
bd1e7a
-{
bd1e7a
-  GObjectClass *object_class = G_OBJECT_CLASS (class);
bd1e7a
-
bd1e7a
-  object_class->finalize = g_keyfile_settings_backend_finalize;
bd1e7a
-
bd1e7a
-  class->read = g_keyfile_settings_backend_read;
bd1e7a
-  class->write = g_keyfile_settings_backend_write;
bd1e7a
-  class->write_tree = g_keyfile_settings_backend_write_tree;
bd1e7a
-  class->reset = g_keyfile_settings_backend_reset;
bd1e7a
-  class->get_writable = g_keyfile_settings_backend_get_writable;
bd1e7a
-  class->get_permission = g_keyfile_settings_backend_get_permission;
bd1e7a
-  /* No need to implement subscribed/unsubscribe: the only point would be to
bd1e7a
-   * stop monitoring the file when there's no GSettings anymore, which is no
bd1e7a
-   * big win.
bd1e7a
-   */
bd1e7a
-}
bd1e7a
-
bd1e7a
 static void
bd1e7a
 file_changed (GFileMonitor      *monitor,
bd1e7a
               GFile             *file,
bd1e7a
@@ -567,6 +558,185 @@ dir_changed (GFileMonitor       *monitor,
bd1e7a
   g_keyfile_settings_backend_keyfile_writable (kfsb);
bd1e7a
 }
bd1e7a
 
bd1e7a
+static void
bd1e7a
+g_keyfile_settings_backend_constructed (GObject *object)
bd1e7a
+{
bd1e7a
+  GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object);
bd1e7a
+
bd1e7a
+  if (kfsb->file == NULL)
bd1e7a
+    {
bd1e7a
+      char *filename = g_build_filename (g_get_user_config_dir (),
bd1e7a
+                                         "glib-2.0", "settings", "keyfile",
bd1e7a
+                                         NULL);
bd1e7a
+      kfsb->file = g_file_new_for_path (filename);
bd1e7a
+      g_free (filename);
bd1e7a
+    }
bd1e7a
+
bd1e7a
+  if (kfsb->prefix == NULL)
bd1e7a
+    {
bd1e7a
+      kfsb->prefix = g_strdup ("/");
bd1e7a
+      kfsb->prefix_len = 1;
bd1e7a
+    }
bd1e7a
+  
bd1e7a
+  kfsb->keyfile = g_key_file_new ();
bd1e7a
+  kfsb->permission = g_simple_permission_new (TRUE);
bd1e7a
+
bd1e7a
+  kfsb->dir = g_file_get_parent (kfsb->file);
bd1e7a
+  g_file_make_directory_with_parents (kfsb->dir, NULL, NULL);
bd1e7a
+
bd1e7a
+  kfsb->file_monitor = g_file_monitor (kfsb->file, G_FILE_MONITOR_NONE, NULL, NULL);
bd1e7a
+  kfsb->dir_monitor = g_file_monitor (kfsb->dir, G_FILE_MONITOR_NONE, NULL, NULL);
bd1e7a
+
bd1e7a
+  compute_checksum (kfsb->digest, NULL, 0);
bd1e7a
+
bd1e7a
+  g_signal_connect (kfsb->file_monitor, "changed",
bd1e7a
+                    G_CALLBACK (file_changed), kfsb);
bd1e7a
+  g_signal_connect (kfsb->dir_monitor, "changed",
bd1e7a
+                    G_CALLBACK (dir_changed), kfsb);
bd1e7a
+
bd1e7a
+  g_keyfile_settings_backend_keyfile_writable (kfsb);
bd1e7a
+  g_keyfile_settings_backend_keyfile_reload (kfsb);
bd1e7a
+}
bd1e7a
+
bd1e7a
+static void
bd1e7a
+g_keyfile_settings_backend_set_property (GObject      *object,
bd1e7a
+                                         guint         prop_id,
bd1e7a
+                                         const GValue *value,
bd1e7a
+                                         GParamSpec   *pspec)
bd1e7a
+{
bd1e7a
+  GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object);
bd1e7a
+
bd1e7a
+  switch (prop_id)
bd1e7a
+    {
bd1e7a
+    case PROP_FILENAME:
bd1e7a
+      /* Construct only. */
bd1e7a
+      g_assert (kfsb->file == NULL);
bd1e7a
+      kfsb->file = g_file_new_for_path (g_value_get_string (value));
bd1e7a
+      break;
bd1e7a
+
bd1e7a
+    case PROP_ROOT_PATH:
bd1e7a
+      /* Construct only. */
bd1e7a
+      g_assert (kfsb->prefix == NULL);
bd1e7a
+      kfsb->prefix = g_value_dup_string (value);
bd1e7a
+      if (kfsb->prefix)
bd1e7a
+        kfsb->prefix_len = strlen (kfsb->prefix);
bd1e7a
+      break;
bd1e7a
+
bd1e7a
+    case PROP_ROOT_GROUP:
bd1e7a
+      /* Construct only. */
bd1e7a
+      g_assert (kfsb->root_group == NULL);
bd1e7a
+      kfsb->root_group = g_value_dup_string (value);
bd1e7a
+      if (kfsb->root_group)
bd1e7a
+        kfsb->root_group_len = strlen (kfsb->root_group);
bd1e7a
+      break;
bd1e7a
+
bd1e7a
+    default:
bd1e7a
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
bd1e7a
+      break;
bd1e7a
+    }
bd1e7a
+}
bd1e7a
+
bd1e7a
+static void
bd1e7a
+g_keyfile_settings_backend_get_property (GObject    *object,
bd1e7a
+                                         guint       prop_id,
bd1e7a
+                                         GValue     *value,
bd1e7a
+                                         GParamSpec *pspec)
bd1e7a
+{
bd1e7a
+  GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object);
bd1e7a
+
bd1e7a
+  switch (prop_id)
bd1e7a
+    {
bd1e7a
+    case PROP_FILENAME:
bd1e7a
+      g_value_set_string (value, g_file_peek_path (kfsb->file));
bd1e7a
+      break;
bd1e7a
+
bd1e7a
+    case PROP_ROOT_PATH:
bd1e7a
+      g_value_set_string (value, kfsb->prefix);
bd1e7a
+      break;
bd1e7a
+
bd1e7a
+    case PROP_ROOT_GROUP:
bd1e7a
+      g_value_set_string (value, kfsb->root_group);
bd1e7a
+      break;
bd1e7a
+
bd1e7a
+    default:
bd1e7a
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
bd1e7a
+      break;
bd1e7a
+    }
bd1e7a
+}
bd1e7a
+
bd1e7a
+static void
bd1e7a
+g_keyfile_settings_backend_class_init (GKeyfileSettingsBackendClass *class)
bd1e7a
+{
bd1e7a
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
bd1e7a
+
bd1e7a
+  object_class->finalize = g_keyfile_settings_backend_finalize;
bd1e7a
+  object_class->constructed = g_keyfile_settings_backend_constructed;
bd1e7a
+  object_class->get_property = g_keyfile_settings_backend_get_property;
bd1e7a
+  object_class->set_property = g_keyfile_settings_backend_set_property;
bd1e7a
+
bd1e7a
+  class->read = g_keyfile_settings_backend_read;
bd1e7a
+  class->write = g_keyfile_settings_backend_write;
bd1e7a
+  class->write_tree = g_keyfile_settings_backend_write_tree;
bd1e7a
+  class->reset = g_keyfile_settings_backend_reset;
bd1e7a
+  class->get_writable = g_keyfile_settings_backend_get_writable;
bd1e7a
+  class->get_permission = g_keyfile_settings_backend_get_permission;
bd1e7a
+  /* No need to implement subscribed/unsubscribe: the only point would be to
bd1e7a
+   * stop monitoring the file when there's no GSettings anymore, which is no
bd1e7a
+   * big win.
bd1e7a
+   */
bd1e7a
+
bd1e7a
+  /**
bd1e7a
+   * GKeyfileSettingsBackend:filename:
bd1e7a
+   *
bd1e7a
+   * The location where the settings are stored on disk.
bd1e7a
+   *
bd1e7a
+   * Defaults to `$XDG_CONFIG_HOME/glib-2.0/settings/keyfile`.
bd1e7a
+   */
bd1e7a
+  g_object_class_install_property (object_class,
bd1e7a
+                                   PROP_FILENAME,
bd1e7a
+                                   g_param_spec_string ("filename",
bd1e7a
+                                                        P_("Filename"),
bd1e7a
+                                                        P_("The filename"),
bd1e7a
+                                                        NULL,
bd1e7a
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
bd1e7a
+                                                        G_PARAM_STATIC_STRINGS));
bd1e7a
+
bd1e7a
+  /**
bd1e7a
+   * GKeyfileSettingsBackend:root-path:
bd1e7a
+   *
bd1e7a
+   * All settings read to or written from the backend must fall under the
bd1e7a
+   * path given in @root_path (which must start and end with a slash and
bd1e7a
+   * not contain two consecutive slashes).  @root_path may be "/".
bd1e7a
+   * 
bd1e7a
+   * Defaults to "/".
bd1e7a
+   */
bd1e7a
+  g_object_class_install_property (object_class,
bd1e7a
+                                   PROP_ROOT_PATH,
bd1e7a
+                                   g_param_spec_string ("root-path",
bd1e7a
+                                                        P_("Root path"),
bd1e7a
+                                                        P_("The root path"),
bd1e7a
+                                                        NULL,
bd1e7a
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
bd1e7a
+                                                        G_PARAM_STATIC_STRINGS));
bd1e7a
+
bd1e7a
+  /**
bd1e7a
+   * GKeyfileSettingsBackend:root-group:
bd1e7a
+   *
bd1e7a
+   * If @root_group is non-%NULL then it specifies the name of the keyfile
bd1e7a
+   * group used for keys that are written directly below the root path.
bd1e7a
+   *
bd1e7a
+   * Defaults to NULL.
bd1e7a
+   */
bd1e7a
+  g_object_class_install_property (object_class,
bd1e7a
+                                   PROP_ROOT_GROUP,
bd1e7a
+                                   g_param_spec_string ("root-group",
bd1e7a
+                                                        P_("Root group"),
bd1e7a
+                                                        P_("The root group"),
bd1e7a
+                                                        NULL,
bd1e7a
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
bd1e7a
+                                                        G_PARAM_STATIC_STRINGS));
bd1e7a
+}
bd1e7a
+
bd1e7a
 /**
bd1e7a
  * g_keyfile_settings_backend_new:
bd1e7a
  * @filename: the filename of the keyfile
bd1e7a
@@ -626,43 +796,15 @@ g_keyfile_settings_backend_new (const gchar *filename,
bd1e7a
                                 const gchar *root_path,
bd1e7a
                                 const gchar *root_group)
bd1e7a
 {
bd1e7a
-  GKeyfileSettingsBackend *kfsb;
bd1e7a
-
bd1e7a
   g_return_val_if_fail (filename != NULL, NULL);
bd1e7a
   g_return_val_if_fail (root_path != NULL, NULL);
bd1e7a
   g_return_val_if_fail (g_str_has_prefix (root_path, "/"), NULL);
bd1e7a
   g_return_val_if_fail (g_str_has_suffix (root_path, "/"), NULL);
bd1e7a
   g_return_val_if_fail (strstr (root_path, "//") == NULL, NULL);
bd1e7a
 
bd1e7a
-  kfsb = g_object_new (G_TYPE_KEYFILE_SETTINGS_BACKEND, NULL);
bd1e7a
-  kfsb->keyfile = g_key_file_new ();
bd1e7a
-  kfsb->permission = g_simple_permission_new (TRUE);
bd1e7a
-
bd1e7a
-  kfsb->file = g_file_new_for_path (filename);
bd1e7a
-  kfsb->dir = g_file_get_parent (kfsb->file);
bd1e7a
-  g_file_make_directory_with_parents (kfsb->dir, NULL, NULL);
bd1e7a
-
bd1e7a
-  kfsb->file_monitor = g_file_monitor (kfsb->file, 0, NULL, NULL);
bd1e7a
-  kfsb->dir_monitor = g_file_monitor (kfsb->dir, 0, NULL, NULL);
bd1e7a
-
bd1e7a
-  kfsb->prefix_len = strlen (root_path);
bd1e7a
-  kfsb->prefix = g_strdup (root_path);
bd1e7a
-
bd1e7a
-  if (root_group)
bd1e7a
-    {
bd1e7a
-      kfsb->root_group_len = strlen (root_group);
bd1e7a
-      kfsb->root_group = g_strdup (root_group);
bd1e7a
-    }
bd1e7a
-
bd1e7a
-  compute_checksum (kfsb->digest, NULL, 0);
bd1e7a
-
bd1e7a
-  g_signal_connect (kfsb->file_monitor, "changed",
bd1e7a
-                    G_CALLBACK (file_changed), kfsb);
bd1e7a
-  g_signal_connect (kfsb->dir_monitor, "changed",
bd1e7a
-                    G_CALLBACK (dir_changed), kfsb);
bd1e7a
-
bd1e7a
-  g_keyfile_settings_backend_keyfile_writable (kfsb);
bd1e7a
-  g_keyfile_settings_backend_keyfile_reload (kfsb);
bd1e7a
-
bd1e7a
-  return G_SETTINGS_BACKEND (kfsb);
bd1e7a
+  return G_SETTINGS_BACKEND (g_object_new (G_TYPE_KEYFILE_SETTINGS_BACKEND,
bd1e7a
+                                           "filename", filename,
bd1e7a
+                                           "root-path", root_path,
bd1e7a
+                                           "root-group", root_group,
bd1e7a
+                                           NULL));
bd1e7a
 }
bd1e7a
diff --git a/gio/gsettingsbackendinternal.h b/gio/gsettingsbackendinternal.h
bd1e7a
index 2a76a80bc..9e1d51dba 100644
bd1e7a
--- a/gio/gsettingsbackendinternal.h
bd1e7a
+++ b/gio/gsettingsbackendinternal.h
bd1e7a
@@ -87,6 +87,8 @@ GType                   g_null_settings_backend_get_type                (void);
bd1e7a
 
bd1e7a
 GType                   g_memory_settings_backend_get_type              (void);
bd1e7a
 
bd1e7a
+GType                   g_keyfile_settings_backend_get_type             (void);
bd1e7a
+
bd1e7a
 #ifdef HAVE_COCOA
bd1e7a
 GType                   g_nextstep_settings_backend_get_type            (void);
bd1e7a
 #endif
bd1e7a
-- 
bd1e7a
2.28.0
bd1e7a
bd1e7a
bd1e7a
From cd448d51f610f1e6a701ac8a1146d3b2048427a0 Mon Sep 17 00:00:00 2001
bd1e7a
From: Matthias Clasen <mclasen@redhat.com>
bd1e7a
Date: Wed, 19 Dec 2018 20:03:29 -0500
bd1e7a
Subject: [PATCH 2/9] settings: Register the keyfile backend as extension
bd1e7a
bd1e7a
This was not done previously because the backend
bd1e7a
could not be instantiated without parameters.
bd1e7a
---
bd1e7a
 gio/gkeyfilesettingsbackend.c | 11 +++++++----
bd1e7a
 1 file changed, 7 insertions(+), 4 deletions(-)
bd1e7a
bd1e7a
diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
bd1e7a
index e8e9f44a5..0e9789cde 100644
bd1e7a
--- a/gio/gkeyfilesettingsbackend.c
bd1e7a
+++ b/gio/gkeyfilesettingsbackend.c
bd1e7a
@@ -32,7 +32,7 @@
bd1e7a
 #include "gfilemonitor.h"
bd1e7a
 #include "gsimplepermission.h"
bd1e7a
 #include "gsettingsbackendinternal.h"
bd1e7a
-#include "giomodule.h"
bd1e7a
+#include "giomodule-priv.h"
bd1e7a
 
bd1e7a
 
bd1e7a
 #define G_TYPE_KEYFILE_SETTINGS_BACKEND      (g_keyfile_settings_backend_get_type ())
bd1e7a
@@ -71,9 +71,12 @@ typedef struct
bd1e7a
   GFileMonitor      *dir_monitor;
bd1e7a
 } GKeyfileSettingsBackend;
bd1e7a
 
bd1e7a
-G_DEFINE_TYPE (GKeyfileSettingsBackend,
bd1e7a
-               g_keyfile_settings_backend,
bd1e7a
-               G_TYPE_SETTINGS_BACKEND)
bd1e7a
+G_DEFINE_TYPE_WITH_CODE (GKeyfileSettingsBackend,
bd1e7a
+                         g_keyfile_settings_backend,
bd1e7a
+                         G_TYPE_SETTINGS_BACKEND,
bd1e7a
+                         _g_io_modules_ensure_extension_points_registered ();
bd1e7a
+                         g_io_extension_point_implement (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME,
bd1e7a
+                                                         g_define_type_id, "keyfile", 10))
bd1e7a
 
bd1e7a
 static void
bd1e7a
 compute_checksum (guint8        *digest,
bd1e7a
-- 
bd1e7a
2.28.0
bd1e7a
bd1e7a
bd1e7a
From 8cbdb7dd496f6c2361eb46ca4c0848d7210fe27a Mon Sep 17 00:00:00 2001
bd1e7a
From: Matthias Clasen <mclasen@redhat.com>
bd1e7a
Date: Mon, 5 Nov 2018 16:07:55 -0500
bd1e7a
Subject: [PATCH 3/9] settings: Add support for defaults to keyfile backend
bd1e7a
bd1e7a
Stacked databases and locks are dconf features that allow
bd1e7a
management software like Fleet Commander to set system-wide
bd1e7a
defaults and overrides centrally for applications.
bd1e7a
bd1e7a
This patch adds minimal support for the same to the keyfile
bd1e7a
backend. We look for a keyfile named 'defaults' and a
bd1e7a
lock-list named 'locks'.
bd1e7a
bd1e7a
Suitable files can be produced from a dconf database with
bd1e7a
dconf dump and dconf list-locks, respectively.
bd1e7a
bd1e7a
The default location for these files is /etc/glib-2.0/settings/.
bd1e7a
For test purposes, this can be overwritten with the
bd1e7a
GSETTINGS_DEFAULTS_DIR environment variable.
bd1e7a
bd1e7a
Writes always go to the per-user keyfile.
bd1e7a
---
bd1e7a
 gio/gkeyfilesettingsbackend.c | 138 ++++++++++++++++++++++++++++++++--
bd1e7a
 1 file changed, 132 insertions(+), 6 deletions(-)
bd1e7a
bd1e7a
diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
bd1e7a
index 0e9789cde..0a4e81511 100644
bd1e7a
--- a/gio/gkeyfilesettingsbackend.c
bd1e7a
+++ b/gio/gkeyfilesettingsbackend.c
bd1e7a
@@ -29,6 +29,7 @@
bd1e7a
 
bd1e7a
 #include "gfile.h"
bd1e7a
 #include "gfileinfo.h"
bd1e7a
+#include "gfileenumerator.h"
bd1e7a
 #include "gfilemonitor.h"
bd1e7a
 #include "gsimplepermission.h"
bd1e7a
 #include "gsettingsbackendinternal.h"
bd1e7a
@@ -45,11 +46,12 @@
bd1e7a
 
bd1e7a
 typedef GSettingsBackendClass GKeyfileSettingsBackendClass;
bd1e7a
 
bd1e7a
-enum {
bd1e7a
+typedef enum {
bd1e7a
   PROP_FILENAME = 1,
bd1e7a
   PROP_ROOT_PATH,
bd1e7a
-  PROP_ROOT_GROUP
bd1e7a
-};
bd1e7a
+  PROP_ROOT_GROUP,
bd1e7a
+  PROP_DEFAULTS_DIR
bd1e7a
+} GKeyfileSettingsBackendProperty;
bd1e7a
 
bd1e7a
 typedef struct
bd1e7a
 {
bd1e7a
@@ -58,6 +60,9 @@ typedef struct
bd1e7a
   GKeyFile          *keyfile;
bd1e7a
   GPermission       *permission;
bd1e7a
   gboolean           writable;
bd1e7a
+  char              *defaults_dir;
bd1e7a
+  GKeyFile          *system_keyfile;
bd1e7a
+  GHashTable        *system_locks; /* Used as a set, owning the strings it contains */
bd1e7a
 
bd1e7a
   gchar             *prefix;
bd1e7a
   gint               prefix_len;
bd1e7a
@@ -196,10 +201,19 @@ get_from_keyfile (GKeyfileSettingsBackend *kfsb,
bd1e7a
   if (convert_path (kfsb, key, &group, &name))
bd1e7a
     {
bd1e7a
       gchar *str;
bd1e7a
+      gchar *sysstr;
bd1e7a
 
bd1e7a
       g_assert (*name);
bd1e7a
 
bd1e7a
+      sysstr = g_key_file_get_value (kfsb->system_keyfile, group, name, NULL);
bd1e7a
       str = g_key_file_get_value (kfsb->keyfile, group, name, NULL);
bd1e7a
+      if (sysstr &&
bd1e7a
+          (g_hash_table_contains (kfsb->system_locks, key) ||
bd1e7a
+           str == NULL))
bd1e7a
+        {
bd1e7a
+          g_free (str);
bd1e7a
+          str = g_steal_pointer (&sysstr);
bd1e7a
+        }
bd1e7a
 
bd1e7a
       if (str)
bd1e7a
         {
bd1e7a
@@ -207,6 +221,8 @@ get_from_keyfile (GKeyfileSettingsBackend *kfsb,
bd1e7a
           g_free (str);
bd1e7a
         }
bd1e7a
 
bd1e7a
+      g_free (sysstr);
bd1e7a
+
bd1e7a
       g_free (group);
bd1e7a
       g_free (name);
bd1e7a
     }
bd1e7a
@@ -221,6 +237,9 @@ set_to_keyfile (GKeyfileSettingsBackend *kfsb,
bd1e7a
 {
bd1e7a
   gchar *group, *name;
bd1e7a
 
bd1e7a
+  if (g_hash_table_contains (kfsb->system_locks, key))
bd1e7a
+    return FALSE;
bd1e7a
+
bd1e7a
   if (convert_path (kfsb, key, &group, &name))
bd1e7a
     {
bd1e7a
       if (value)
bd1e7a
@@ -368,7 +387,9 @@ g_keyfile_settings_backend_get_writable (GSettingsBackend *backend,
bd1e7a
 {
bd1e7a
   GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (backend);
bd1e7a
 
bd1e7a
-  return kfsb->writable && path_is_valid (kfsb, name);
bd1e7a
+  return kfsb->writable &&
bd1e7a
+         !g_hash_table_contains (kfsb->system_locks, name) &&
bd1e7a
+         path_is_valid (kfsb, name);
bd1e7a
 }
bd1e7a
 
bd1e7a
 static GPermission *
bd1e7a
@@ -514,6 +535,9 @@ g_keyfile_settings_backend_finalize (GObject *object)
bd1e7a
 
bd1e7a
   g_key_file_free (kfsb->keyfile);
bd1e7a
   g_object_unref (kfsb->permission);
bd1e7a
+  g_key_file_unref (kfsb->system_keyfile);
bd1e7a
+  g_hash_table_unref (kfsb->system_locks);
bd1e7a
+  g_free (kfsb->defaults_dir);
bd1e7a
 
bd1e7a
   g_file_monitor_cancel (kfsb->file_monitor);
bd1e7a
   g_object_unref (kfsb->file_monitor);
bd1e7a
@@ -561,6 +585,75 @@ dir_changed (GFileMonitor       *monitor,
bd1e7a
   g_keyfile_settings_backend_keyfile_writable (kfsb);
bd1e7a
 }
bd1e7a
 
bd1e7a
+static void
bd1e7a
+load_system_settings (GKeyfileSettingsBackend *kfsb)
bd1e7a
+{
bd1e7a
+  GError *error = NULL;
bd1e7a
+  const char *dir = "/etc/glib-2.0/settings";
bd1e7a
+  char *path;
bd1e7a
+  char *contents;
bd1e7a
+
bd1e7a
+  kfsb->system_keyfile = g_key_file_new ();
bd1e7a
+  kfsb->system_locks = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
bd1e7a
+
bd1e7a
+  if (kfsb->defaults_dir)
bd1e7a
+    dir = kfsb->defaults_dir;
bd1e7a
+
bd1e7a
+  path = g_build_filename (dir, "defaults", NULL);
bd1e7a
+
bd1e7a
+  /* The defaults are in the same keyfile format that we use for the settings.
bd1e7a
+   * It can be produced from a dconf database using: dconf dump
bd1e7a
+   */
bd1e7a
+  if (!g_key_file_load_from_file (kfsb->system_keyfile, path, G_KEY_FILE_NONE, &error))
bd1e7a
+    {
bd1e7a
+      if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
bd1e7a
+        g_warning ("Failed to read %s: %s", path, error->message);
bd1e7a
+      g_clear_error (&error);
bd1e7a
+    }
bd1e7a
+  else
bd1e7a
+    g_debug ("Loading default settings from %s", path);
bd1e7a
+
bd1e7a
+  g_free (path);
bd1e7a
+
bd1e7a
+  path = g_build_filename (dir, "locks", NULL);
bd1e7a
+
bd1e7a
+  /* The locks file is a text file containing a list paths to lock, one per line.
bd1e7a
+   * It can be produced from a dconf database using: dconf list-locks
bd1e7a
+   */
bd1e7a
+  if (!g_file_get_contents (path, &contents, NULL, &error))
bd1e7a
+    {
bd1e7a
+      if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
bd1e7a
+        g_warning ("Failed to read %s: %s", path, error->message);
bd1e7a
+      g_clear_error (&error);
bd1e7a
+    }
bd1e7a
+  else
bd1e7a
+    {
bd1e7a
+      char **lines;
bd1e7a
+      gsize i;
bd1e7a
+
bd1e7a
+      g_debug ("Loading locks from %s", path);
bd1e7a
+
bd1e7a
+      lines = g_strsplit (contents, "\n", 0);
bd1e7a
+      for (i = 0; lines[i]; i++)
bd1e7a
+        {
bd1e7a
+          char *line = lines[i];
bd1e7a
+          if (line[0] == '#' || line[0] == '\0')
bd1e7a
+            {
bd1e7a
+              g_free (line);
bd1e7a
+              continue;
bd1e7a
+            }
bd1e7a
+
bd1e7a
+          g_debug ("Locking key %s", line);
bd1e7a
+          g_hash_table_add (kfsb->system_locks, g_steal_pointer (&line));
bd1e7a
+        }
bd1e7a
+
bd1e7a
+      g_free (lines);
bd1e7a
+    }
bd1e7a
+  g_free (contents);
bd1e7a
+
bd1e7a
+  g_free (path);
bd1e7a
+}
bd1e7a
+
bd1e7a
 static void
bd1e7a
 g_keyfile_settings_backend_constructed (GObject *object)
bd1e7a
 {
bd1e7a
@@ -599,6 +692,8 @@ g_keyfile_settings_backend_constructed (GObject *object)
bd1e7a
 
bd1e7a
   g_keyfile_settings_backend_keyfile_writable (kfsb);
bd1e7a
   g_keyfile_settings_backend_keyfile_reload (kfsb);
bd1e7a
+
bd1e7a
+  load_system_settings (kfsb);
bd1e7a
 }
bd1e7a
 
bd1e7a
 static void
bd1e7a
@@ -609,7 +704,7 @@ g_keyfile_settings_backend_set_property (GObject      *object,
bd1e7a
 {
bd1e7a
   GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object);
bd1e7a
 
bd1e7a
-  switch (prop_id)
bd1e7a
+  switch ((GKeyfileSettingsBackendProperty)prop_id)
bd1e7a
     {
bd1e7a
     case PROP_FILENAME:
bd1e7a
       /* Construct only. */
bd1e7a
@@ -633,6 +728,12 @@ g_keyfile_settings_backend_set_property (GObject      *object,
bd1e7a
         kfsb->root_group_len = strlen (kfsb->root_group);
bd1e7a
       break;
bd1e7a
 
bd1e7a
+    case PROP_DEFAULTS_DIR:
bd1e7a
+      /* Construct only. */
bd1e7a
+      g_assert (kfsb->defaults_dir == NULL);
bd1e7a
+      kfsb->defaults_dir = g_value_dup_string (value);
bd1e7a
+      break;
bd1e7a
+
bd1e7a
     default:
bd1e7a
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
bd1e7a
       break;
bd1e7a
@@ -647,7 +748,7 @@ g_keyfile_settings_backend_get_property (GObject    *object,
bd1e7a
 {
bd1e7a
   GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object);
bd1e7a
 
bd1e7a
-  switch (prop_id)
bd1e7a
+  switch ((GKeyfileSettingsBackendProperty)prop_id)
bd1e7a
     {
bd1e7a
     case PROP_FILENAME:
bd1e7a
       g_value_set_string (value, g_file_peek_path (kfsb->file));
bd1e7a
@@ -661,6 +762,10 @@ g_keyfile_settings_backend_get_property (GObject    *object,
bd1e7a
       g_value_set_string (value, kfsb->root_group);
bd1e7a
       break;
bd1e7a
 
bd1e7a
+    case PROP_DEFAULTS_DIR:
bd1e7a
+      g_value_set_string (value, kfsb->defaults_dir);
bd1e7a
+      break;
bd1e7a
+
bd1e7a
     default:
bd1e7a
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
bd1e7a
       break;
bd1e7a
@@ -738,6 +843,22 @@ g_keyfile_settings_backend_class_init (GKeyfileSettingsBackendClass *class)
bd1e7a
                                                         NULL,
bd1e7a
                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
bd1e7a
                                                         G_PARAM_STATIC_STRINGS));
bd1e7a
+
bd1e7a
+  /**
bd1e7a
+   * GKeyfileSettingsBackend:default-dir:
bd1e7a
+   *
bd1e7a
+   * The directory where the system defaults and locks are located.
bd1e7a
+   *
bd1e7a
+   * Defaults to `/etc/glib-2.0/settings`.
bd1e7a
+   */
bd1e7a
+  g_object_class_install_property (object_class,
bd1e7a
+                                   PROP_DEFAULTS_DIR,
bd1e7a
+                                   g_param_spec_string ("defaults-dir",
bd1e7a
+                                                        P_("Default dir"),
bd1e7a
+                                                        P_("Defaults dir"),
bd1e7a
+                                                        NULL,
bd1e7a
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
bd1e7a
+                                                        G_PARAM_STATIC_STRINGS));
bd1e7a
 }
bd1e7a
 
bd1e7a
 /**
bd1e7a
@@ -792,6 +913,11 @@ g_keyfile_settings_backend_class_init (GKeyfileSettingsBackendClass *class)
bd1e7a
  * characters in your path names or '=' in your key names you may be in
bd1e7a
  * trouble.
bd1e7a
  *
bd1e7a
+ * The backend reads default values from a keyfile called `defaults` in
bd1e7a
+ * the directory specified by the #GKeyfileSettingsBackend:defaults-dir property,
bd1e7a
+ * and a list of locked keys from a text file with the name `locks` in
bd1e7a
+ * the same location.
bd1e7a
+ *
bd1e7a
  * Returns: (transfer full): a keyfile-backed #GSettingsBackend
bd1e7a
  **/
bd1e7a
 GSettingsBackend *
bd1e7a
-- 
bd1e7a
2.28.0
bd1e7a
bd1e7a
bd1e7a
From 93dceb39fe2de23aeffe40ff02c824393c749270 Mon Sep 17 00:00:00 2001
bd1e7a
From: Matthias Clasen <mclasen@redhat.com>
bd1e7a
Date: Fri, 2 Nov 2018 23:00:49 -0400
bd1e7a
Subject: [PATCH 4/9] settings: Prefer the keyfile backend when sandboxed
bd1e7a
bd1e7a
When we are in a sandboxed situation, bump the priority
bd1e7a
of the keyfile settings backend above the dconf one,
bd1e7a
so we use a keyfile inside the sandbox instead of requiring
bd1e7a
holes in the sandbox for dconf.
bd1e7a
---
bd1e7a
 gio/gkeyfilesettingsbackend.c | 9 ++++++++-
bd1e7a
 1 file changed, 8 insertions(+), 1 deletion(-)
bd1e7a
bd1e7a
diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
bd1e7a
index 0a4e81511..398cb053a 100644
bd1e7a
--- a/gio/gkeyfilesettingsbackend.c
bd1e7a
+++ b/gio/gkeyfilesettingsbackend.c
bd1e7a
@@ -34,6 +34,7 @@
bd1e7a
 #include "gsimplepermission.h"
bd1e7a
 #include "gsettingsbackendinternal.h"
bd1e7a
 #include "giomodule-priv.h"
bd1e7a
+#include "gportalsupport.h"
bd1e7a
 
bd1e7a
 
bd1e7a
 #define G_TYPE_KEYFILE_SETTINGS_BACKEND      (g_keyfile_settings_backend_get_type ())
bd1e7a
@@ -76,12 +77,18 @@ typedef struct
bd1e7a
   GFileMonitor      *dir_monitor;
bd1e7a
 } GKeyfileSettingsBackend;
bd1e7a
 
bd1e7a
+#ifdef G_OS_WIN32
bd1e7a
+#define EXTENSION_PRIORITY 10
bd1e7a
+#else
bd1e7a
+#define EXTENSION_PRIORITY (glib_should_use_portal () ? 110 : 10)
bd1e7a
+#endif
bd1e7a
+
bd1e7a
 G_DEFINE_TYPE_WITH_CODE (GKeyfileSettingsBackend,
bd1e7a
                          g_keyfile_settings_backend,
bd1e7a
                          G_TYPE_SETTINGS_BACKEND,
bd1e7a
                          _g_io_modules_ensure_extension_points_registered ();
bd1e7a
                          g_io_extension_point_implement (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME,
bd1e7a
-                                                         g_define_type_id, "keyfile", 10))
bd1e7a
+                                                         g_define_type_id, "keyfile", EXTENSION_PRIORITY))
bd1e7a
 
bd1e7a
 static void
bd1e7a
 compute_checksum (guint8        *digest,
bd1e7a
-- 
bd1e7a
2.28.0
bd1e7a
bd1e7a
bd1e7a
From 5d0d49750564aa7fd9e7d0d58c08a08847570921 Mon Sep 17 00:00:00 2001
bd1e7a
From: Matthias Clasen <mclasen@redhat.com>
bd1e7a
Date: Mon, 21 Jan 2019 22:55:45 -0500
bd1e7a
Subject: [PATCH 5/9] keyfile settings: Accept unquoted strings
bd1e7a
bd1e7a
It is hard for users to remember that strings have to be explicitly
bd1e7a
quoted in the keyfile. Be lenient and accept strings that lack those
bd1e7a
quotes.
bd1e7a
---
bd1e7a
 gio/gkeyfilesettingsbackend.c | 19 +++++++++++++++++++
bd1e7a
 gio/tests/gsettings.c         | 17 +++++++++++++++++
bd1e7a
 2 files changed, 36 insertions(+)
bd1e7a
bd1e7a
diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
bd1e7a
index 398cb053a..d5796b706 100644
bd1e7a
--- a/gio/gkeyfilesettingsbackend.c
bd1e7a
+++ b/gio/gkeyfilesettingsbackend.c
bd1e7a
@@ -225,6 +225,25 @@ get_from_keyfile (GKeyfileSettingsBackend *kfsb,
bd1e7a
       if (str)
bd1e7a
         {
bd1e7a
           return_value = g_variant_parse (type, str, NULL, NULL, NULL);
bd1e7a
+          if (return_value == NULL &&
bd1e7a
+              g_variant_type_equal (type, G_VARIANT_TYPE_STRING) &&
bd1e7a
+              str[0] != '\"')
bd1e7a
+            {
bd1e7a
+              GString *s = g_string_sized_new (strlen (str) + 2);
bd1e7a
+              char *p = str;
bd1e7a
+
bd1e7a
+              g_string_append_c (s, '\"');
bd1e7a
+              while (*p)
bd1e7a
+                {
bd1e7a
+                  if (*p == '\"')
bd1e7a
+                    g_string_append_c (s, '\\');
bd1e7a
+                  g_string_append_c (s, *p);
bd1e7a
+                  p++;
bd1e7a
+                }
bd1e7a
+              g_string_append_c (s, '\"');
bd1e7a
+              return_value = g_variant_parse (type, s->str, NULL, NULL, NULL);
bd1e7a
+              g_string_free (s, TRUE);
bd1e7a
+            }
bd1e7a
           g_free (str);
bd1e7a
         }
bd1e7a
 
bd1e7a
diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c
bd1e7a
index 2be4122fe..6eb49f124 100644
bd1e7a
--- a/gio/tests/gsettings.c
bd1e7a
+++ b/gio/tests/gsettings.c
bd1e7a
@@ -1716,6 +1716,23 @@ test_keyfile (void)
bd1e7a
   g_assert_cmpstr (str, ==, "howdy");
bd1e7a
   g_free (str);
bd1e7a
 
bd1e7a
+  /* Now check setting a string without quotes */
bd1e7a
+  called = FALSE;
bd1e7a
+  g_signal_connect (settings, "changed::greeting", G_CALLBACK (key_changed_cb), &called);
bd1e7a
+
bd1e7a
+  g_key_file_set_string (keyfile, "tests", "greeting", "he\"l🤗uń");
bd1e7a
+  g_free (data);
bd1e7a
+  data = g_key_file_to_data (keyfile, &len, NULL);
bd1e7a
+  g_file_set_contents ("keyfile/gsettings.store", data, len, &error);
bd1e7a
+  g_assert_no_error (error);
bd1e7a
+  while (!called)
bd1e7a
+    g_main_context_iteration (NULL, FALSE);
bd1e7a
+  g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called);
bd1e7a
+
bd1e7a
+  str = g_settings_get_string (settings, "greeting");
bd1e7a
+  g_assert_cmpstr (str, ==, "he\"l🤗uń");
bd1e7a
+  g_free (str);
bd1e7a
+
bd1e7a
   g_settings_set (settings, "farewell", "s", "cheerio");
bd1e7a
   
bd1e7a
   called = FALSE;
bd1e7a
-- 
bd1e7a
2.28.0
bd1e7a
bd1e7a
bd1e7a
From 3765e73f9a2dbbc6863bcffdee85ffb18530c89b Mon Sep 17 00:00:00 2001
bd1e7a
From: Philip Withnall <withnall@endlessm.com>
bd1e7a
Date: Wed, 23 Jan 2019 15:14:58 +0000
bd1e7a
Subject: [PATCH 6/9] gkeyfilesettingsbackend: Add a code comment to clarify
bd1e7a
 things
bd1e7a
bd1e7a
Signed-off-by: Philip Withnall <withnall@endlessm.com>
bd1e7a
---
bd1e7a
 gio/gkeyfilesettingsbackend.c | 4 ++++
bd1e7a
 1 file changed, 4 insertions(+)
bd1e7a
bd1e7a
diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
bd1e7a
index d5796b706..5ea632305 100644
bd1e7a
--- a/gio/gkeyfilesettingsbackend.c
bd1e7a
+++ b/gio/gkeyfilesettingsbackend.c
bd1e7a
@@ -225,6 +225,10 @@ get_from_keyfile (GKeyfileSettingsBackend *kfsb,
bd1e7a
       if (str)
bd1e7a
         {
bd1e7a
           return_value = g_variant_parse (type, str, NULL, NULL, NULL);
bd1e7a
+
bd1e7a
+          /* As a special case, support values of type %G_VARIANT_TYPE_STRING
bd1e7a
+           * not being quoted, since users keep forgetting to do it and then
bd1e7a
+           * getting confused. */
bd1e7a
           if (return_value == NULL &&
bd1e7a
               g_variant_type_equal (type, G_VARIANT_TYPE_STRING) &&
bd1e7a
               str[0] != '\"')
bd1e7a
-- 
bd1e7a
2.28.0
bd1e7a
bd1e7a
bd1e7a
From 1df628861afe027e8dce5e27f4249059bad6bc60 Mon Sep 17 00:00:00 2001
bd1e7a
From: Matthias Clasen <mclasen@redhat.com>
bd1e7a
Date: Wed, 10 Jul 2019 11:14:03 -0400
bd1e7a
Subject: [PATCH 7/9] key file: Handle filename being NULL
bd1e7a
bd1e7a
This happens when we are default-constructed
bd1e7a
without explicit arguments.
bd1e7a
bd1e7a
Closes: https://gitlab.gnome.org/GNOME/glib/issues/1825
bd1e7a
---
bd1e7a
 gio/gkeyfilesettingsbackend.c | 3 ++-
bd1e7a
 1 file changed, 2 insertions(+), 1 deletion(-)
bd1e7a
bd1e7a
diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
bd1e7a
index 5ea632305..a874af287 100644
bd1e7a
--- a/gio/gkeyfilesettingsbackend.c
bd1e7a
+++ b/gio/gkeyfilesettingsbackend.c
bd1e7a
@@ -739,7 +739,8 @@ g_keyfile_settings_backend_set_property (GObject      *object,
bd1e7a
     case PROP_FILENAME:
bd1e7a
       /* Construct only. */
bd1e7a
       g_assert (kfsb->file == NULL);
bd1e7a
-      kfsb->file = g_file_new_for_path (g_value_get_string (value));
bd1e7a
+      if (g_value_get_string (value))
bd1e7a
+        kfsb->file = g_file_new_for_path (g_value_get_string (value));
bd1e7a
       break;
bd1e7a
 
bd1e7a
     case PROP_ROOT_PATH:
bd1e7a
-- 
bd1e7a
2.28.0
bd1e7a
bd1e7a
bd1e7a
From 9c5d3a6081e5ff419db96d9651bddbfcdb8b1bc6 Mon Sep 17 00:00:00 2001
bd1e7a
From: Matthias Clasen <mclasen@redhat.com>
bd1e7a
Date: Fri, 12 Jul 2019 11:30:30 -0400
bd1e7a
Subject: [PATCH] portal: Add a getter for dconf access
bd1e7a
bd1e7a
Add method to find whether the sandbox provides
bd1e7a
access to dconf. This will be used to tweak
bd1e7a
the priorities for the keyfile settings backend.
bd1e7a
---
bd1e7a
 gio/gportalsupport.c | 18 ++++++++++++++++++
bd1e7a
 gio/gportalsupport.h |  1 +
bd1e7a
 2 files changed, 19 insertions(+)
bd1e7a
bd1e7a
diff --git a/gio/gportalsupport.c b/gio/gportalsupport.c
bd1e7a
index 2f1e82517..b0a94b360 100644
bd1e7a
--- a/gio/gportalsupport.c
bd1e7a
+++ b/gio/gportalsupport.c
bd1e7a
@@ -23,6 +23,7 @@
bd1e7a
 static gboolean flatpak_info_read;
bd1e7a
 static gboolean use_portal;
bd1e7a
 static gboolean network_available;
bd1e7a
+static gboolean dconf_access;
bd1e7a
 
bd1e7a
 static void
bd1e7a
 read_flatpak_info (void)
bd1e7a
@@ -40,11 +41,13 @@ read_flatpak_info (void)
bd1e7a
 
bd1e7a
       use_portal = TRUE;
bd1e7a
       network_available = FALSE;
bd1e7a
+      dconf_access = FALSE;
bd1e7a
 
bd1e7a
       keyfile = g_key_file_new ();
bd1e7a
       if (g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, NULL))
bd1e7a
         {
bd1e7a
           char **shared = NULL;
bd1e7a
+          char *dconf_policy = NULL;
bd1e7a
 
bd1e7a
           shared = g_key_file_get_string_list (keyfile, "Context", "shared", NULL, NULL);
bd1e7a
           if (shared)
bd1e7a
@@ -52,6 +55,14 @@ read_flatpak_info (void)
bd1e7a
               network_available = g_strv_contains ((const char * const *)shared, "network");
bd1e7a
               g_strfreev (shared);
bd1e7a
             }
bd1e7a
+
bd1e7a
+          dconf_policy = g_key_file_get_string (keyfile, "Session Bus Policy", "ca.desrt.dconf", NULL);
bd1e7a
+          if (dconf_policy)
bd1e7a
+            {
bd1e7a
+              if (strcmp (dconf_policy, "talk") == 0)
bd1e7a
+                dconf_access = TRUE;
bd1e7a
+              g_free (dconf_policy);
bd1e7a
+            }
bd1e7a
         }
bd1e7a
 
bd1e7a
       g_key_file_unref (keyfile);
bd1e7a
@@ -64,6 +75,7 @@ read_flatpak_info (void)
bd1e7a
       if (var && var[0] == '1')
bd1e7a
         use_portal = TRUE;
bd1e7a
       network_available = TRUE;
bd1e7a
+      dconf_access = TRUE;
bd1e7a
     }
bd1e7a
 }
bd1e7a
 
bd1e7a
@@ -81,3 +93,9 @@ glib_network_available_in_sandbox (void)
bd1e7a
   return network_available;
bd1e7a
 }
bd1e7a
 
bd1e7a
+gboolean
bd1e7a
+glib_has_dconf_access_in_sandbox (void)
bd1e7a
+{
bd1e7a
+  read_flatpak_info ();
bd1e7a
+  return dconf_access;
bd1e7a
+}
bd1e7a
diff --git a/gio/gportalsupport.h b/gio/gportalsupport.h
bd1e7a
index a331f45d3..746f1fd6b 100644
bd1e7a
--- a/gio/gportalsupport.h
bd1e7a
+++ b/gio/gportalsupport.h
bd1e7a
@@ -24,6 +24,7 @@ G_BEGIN_DECLS
bd1e7a
 
bd1e7a
 gboolean glib_should_use_portal (void);
bd1e7a
 gboolean glib_network_available_in_sandbox (void);
bd1e7a
+gboolean glib_has_dconf_access_in_sandbox (void);
bd1e7a
 
bd1e7a
 G_END_DECLS
bd1e7a
 
bd1e7a
-- 
bd1e7a
GitLab
bd1e7a
bd1e7a
bd1e7a
From e6461f208931e27b52d82f7d3b5a7ce4fc26c9d7 Mon Sep 17 00:00:00 2001
bd1e7a
From: Matthias Clasen <mclasen@redhat.com>
bd1e7a
Date: Fri, 12 Jul 2019 11:31:37 -0400
bd1e7a
Subject: [PATCH 8/9] settings: Tweak priorities for keyfile backend
bd1e7a
bd1e7a
We want to use the keyfile backend in sandboxes,
bd1e7a
but we want to avoid people losing their existing
bd1e7a
settings that are stored in dconf. Flatpak does
bd1e7a
a migration from dconf to keyfile, but only if
bd1e7a
the app explictly requests it.
bd1e7a
bd1e7a
From an app perspective, there are two steps to
bd1e7a
the dconf->keyfile migration:
bd1e7a
1. Request that flatpak do the migration, by adding
bd1e7a
   the migrate-path key to the metadata
bd1e7a
2. Stop adding the 'dconf hole' to the sandbox
bd1e7a
bd1e7a
To keep us from switching to the keyfile backend
bd1e7a
prematurely, look at whether the app has stopped
bd1e7a
requesting a 'dconf hole' in the sandbox.
bd1e7a
---
bd1e7a
 gio/gkeyfilesettingsbackend.c | 2 +-
bd1e7a
 1 file changed, 1 insertion(+), 1 deletion(-)
bd1e7a
bd1e7a
diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
bd1e7a
index a874af287..f5358818e 100644
bd1e7a
--- a/gio/gkeyfilesettingsbackend.c
bd1e7a
+++ b/gio/gkeyfilesettingsbackend.c
bd1e7a
@@ -80,7 +80,7 @@ typedef struct
bd1e7a
 #ifdef G_OS_WIN32
bd1e7a
 #define EXTENSION_PRIORITY 10
bd1e7a
 #else
bd1e7a
-#define EXTENSION_PRIORITY (glib_should_use_portal () ? 110 : 10)
bd1e7a
+#define EXTENSION_PRIORITY (glib_should_use_portal () && !glib_has_dconf_access_in_sandbox () ? 110 : 10)
bd1e7a
 #endif
bd1e7a
 
bd1e7a
 G_DEFINE_TYPE_WITH_CODE (GKeyfileSettingsBackend,
bd1e7a
-- 
bd1e7a
2.28.0
bd1e7a
bd1e7a
bd1e7a
From 5f8d787815dc220fa2e288e03cd0cb9497727753 Mon Sep 17 00:00:00 2001
bd1e7a
From: Matthias Clasen <mclasen@redhat.com>
bd1e7a
Date: Mon, 8 Jul 2019 10:31:51 -0400
bd1e7a
Subject: [PATCH] Ensure that the keyfile settings backend exists
bd1e7a
bd1e7a
We need to bring the type into existence.
bd1e7a
bd1e7a
Closes: https://gitlab.gnome.org/GNOME/glib/issues/1822
bd1e7a
---
bd1e7a
 gio/giomodule.c | 1 +
bd1e7a
 1 file changed, 1 insertion(+)
bd1e7a
bd1e7a
diff --git a/gio/giomodule.c b/gio/giomodule.c
bd1e7a
index 9bb28985a..1007abdbf 100644
bd1e7a
--- a/gio/giomodule.c
bd1e7a
+++ b/gio/giomodule.c
bd1e7a
@@ -1211,6 +1211,7 @@ _g_io_modules_ensure_loaded (void)
bd1e7a
       /* Initialize types from built-in "modules" */
bd1e7a
       g_type_ensure (g_null_settings_backend_get_type ());
bd1e7a
       g_type_ensure (g_memory_settings_backend_get_type ());
bd1e7a
+      g_type_ensure (g_keyfile_settings_backend_get_type ());
bd1e7a
 #if defined(HAVE_INOTIFY_INIT1)
bd1e7a
       g_type_ensure (g_inotify_file_monitor_get_type ());
bd1e7a
 #endif
bd1e7a
-- 
bd1e7a
GitLab