[Libreoffice-commits] core.git: config_host/config_dconf.h.in config_host.mk.in configmgr/CppunitTest_configmgr_unit.mk configmgr/Library_configmgr.mk configmgr/source configure.ac distro-configs/LibreOfficeLinux.conf include/sal instsetoo_native/CustomTarget_setup.mk RepositoryExternal.mk scp2/source

Stephan Bergmann sbergman at redhat.com
Wed Jul 8 05:06:40 PDT 2015


 RepositoryExternal.mk                   |    5 
 config_host.mk.in                       |    3 
 config_host/config_dconf.h.in           |   17 
 configmgr/CppunitTest_configmgr_unit.mk |    1 
 configmgr/Library_configmgr.mk          |    8 
 configmgr/source/components.cxx         |   14 
 configmgr/source/readdconflayer.cxx     |  931 ++++++++++++++++++++++++++++++++
 configmgr/source/readdconflayer.hxx     |   25 
 configure.ac                            |   29 
 distro-configs/LibreOfficeLinux.conf    |    1 
 include/sal/log-areas.dox               |    1 
 instsetoo_native/CustomTarget_setup.mk  |    2 
 scp2/source/ooo/common_brand.scp        |   19 
 13 files changed, 1048 insertions(+), 8 deletions(-)

New commits:
commit ecc617e797aa5ed329668114e54ec7ffa5c0e87b
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Wed Jul 8 11:20:19 2015 +0200

    configmgr: support reading from a dconf layer (WIP)
    
    Work in progress to allow integration of LO with
    <https://wiki.gnome.org/Projects/FleetCommander>.
    
    During configuration, dconf support is implicitly enabled when available on the
    host (which is presumably only available on Linux).  It is explicitly disabled
    for TDF Linux builds for now, though, to avoid accidental dependencies of the
    distributed installation sets on system dconf libraries.
    
    A dconf layer is represented in the CONFIGURATION_LAYERS bootstrap variable with
    type "dconf" and an empty URL.  See the comment at the top of
    configmgr/source/readdconflayer.cxx for the encoding of component-data in dconf.
    
    All of this is still subject to change.
    
    Change-Id: I2d08d81c8ea43ba4a99040a8882ae75b91bcfdb9
    Reviewed-on: https://gerrit.libreoffice.org/16848
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>

diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index a0a0d61..75f033f 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -3584,6 +3584,11 @@ endif # ENABLE_COLLADA
 
 endif # ENABLE_GLTF
 
+define gb_LinkTarget__use_dconf
+$(call gb_LinkTarget_add_defs,$(1),$(DCONF_CFLAGS))
+$(call gb_LinkTarget_add_libs,$(1),$(DCONF_LIBS))
+endef
+
 ### Jars ############################################################
 
 ifneq ($(SYSTEM_HSQLDB),)
diff --git a/config_host.mk.in b/config_host.mk.in
index 1d0702b..2a20b8b 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -91,6 +91,8 @@ export DBUSMENUGTK_CFLAGS=$(gb_SPACE)@DBUSMENUGTK_CFLAGS@
 export DBUSMENUGTK_LIBS=$(gb_SPACE)@DBUSMENUGTK_LIBS@
 export DBUS_CFLAGS=$(gb_SPACE)@DBUS_CFLAGS@
 export DBUS_LIBS=$(gb_SPACE)@DBUS_LIBS@
+export DCONF_CFLAGS=@DCONF_CFLAGS@
+export DCONF_LIBS=@DCONF_LIBS@
 export DEFAULT_BRAND_IMAGES=@DEFAULT_BRAND_IMAGES@
 export DIAGRAM_EXTENSION_PACK=@DIAGRAM_EXTENSION_PACK@
 export DICT_SYSTEM_DIR=@DICT_SYSTEM_DIR@
@@ -122,6 +124,7 @@ export ENABLE_CUPS=@ENABLE_CUPS@
 export ENABLE_CURL=@ENABLE_CURL@
 export ENABLE_DBGUTIL=@ENABLE_DBGUTIL@
 export ENABLE_DBUS=@ENABLE_DBUS@
+export ENABLE_DCONF=@ENABLE_DCONF@
 export ENABLE_DEBUG=@ENABLE_DEBUG@
 export ENABLE_DEBUGINFO_FOR=@ENABLE_DEBUGINFO_FOR@
 export ENABLE_DIRECTX=@ENABLE_DIRECTX@
diff --git a/config_host/config_dconf.h.in b/config_host/config_dconf.h.in
new file mode 100644
index 0000000..09608c4
--- /dev/null
+++ b/config_host/config_dconf.h.in
@@ -0,0 +1,17 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_CONFIG_DCONF_H
+#define INCLUDED_CONFIG_DCONF_H
+
+#define ENABLE_DCONF 0
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/configmgr/CppunitTest_configmgr_unit.mk b/configmgr/CppunitTest_configmgr_unit.mk
index 1672c9f..e8bddc2 100644
--- a/configmgr/CppunitTest_configmgr_unit.mk
+++ b/configmgr/CppunitTest_configmgr_unit.mk
@@ -49,5 +49,6 @@ $(eval $(call gb_CppunitTest_use_components,configmgr_unit,\
 
 $(eval $(call gb_CppunitTest_use_externals,configmgr_unit,\
     boost_headers \
+    dconf \
     icu_headers \
 ))
diff --git a/configmgr/Library_configmgr.mk b/configmgr/Library_configmgr.mk
index 528b150..36c316a 100644
--- a/configmgr/Library_configmgr.mk
+++ b/configmgr/Library_configmgr.mk
@@ -38,15 +38,19 @@ $(eval $(call gb_Library_add_exception_objects,configmgr, \
     configmgr/source/type \
     configmgr/source/update \
     configmgr/source/valueparser \
-    $(if $(filter $(OS),WNT), configmgr/source/winreg ) \
     configmgr/source/writemodfile \
     configmgr/source/xcdparser \
     configmgr/source/xcsparser \
     configmgr/source/xcuparser \
     configmgr/source/xmldata \
+    $(if $(ENABLE_DCONF),configmgr/source/readdconflayer) \
+    $(if $(filter $(OS),WNT),configmgr/source/winreg) \
 ))
 
-$(eval $(call gb_Library_use_external,configmgr,boost_headers))
+$(eval $(call gb_Library_use_externals,configmgr, \
+    boost_headers \
+    dconf \
+))
 
 $(eval $(call gb_Library_use_sdk_api,configmgr))
 
diff --git a/configmgr/source/components.cxx b/configmgr/source/components.cxx
index dc0c4be..4b1eaea 100644
--- a/configmgr/source/components.cxx
+++ b/configmgr/source/components.cxx
@@ -36,6 +36,7 @@
 #include <com/sun/star/uno/RuntimeException.hpp>
 #include <com/sun/star/uno/XComponentContext.hpp>
 #include <com/sun/star/uno/XInterface.hpp>
+#include <config_dconf.h>
 #include <config_folders.h>
 #include <osl/conditn.hxx>
 #include <osl/file.hxx>
@@ -64,6 +65,10 @@
 #include "xcuparser.hxx"
 #include "xcsparser.hxx"
 
+#if ENABLE_DCONF
+#include <readdconflayer.hxx>
+#endif
+
 #if defined WNT
 #include "winreg.hxx"
 #endif
@@ -522,6 +527,15 @@ Components::Components(
             parseResLayer(layer, url);
             SAL_INFO("configmgr", "parseResLayer() took " << (osl_getGlobalTimer() - nStartTime) << " ms");
             ++layer; //TODO: overflow
+#if ENABLE_DCONF
+        } else if (type == "dconf") {
+            if (!url.isEmpty()) {
+                throw css::uno::RuntimeException(
+                    "CONFIGURATION_LAYERS: non-empty \"dconf\" URL");
+            }
+            readDconfLayer(data_, layer);
+            ++layer; //TODO: overflow
+#endif
 #if defined WNT
         } else if (type == "winreg") {
             if (!url.isEmpty()) {
diff --git a/configmgr/source/readdconflayer.cxx b/configmgr/source/readdconflayer.cxx
new file mode 100644
index 0000000..62e6a65
--- /dev/null
+++ b/configmgr/source/readdconflayer.cxx
@@ -0,0 +1,931 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <limits>
+#include <type_traits>
+
+#include <dconf/dconf.h>
+
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <data.hxx>
+#include <groupnode.hxx>
+#include <localizedpropertynode.hxx>
+#include <localizedvaluenode.hxx>
+#include <nodemap.hxx>
+#include <propertynode.hxx>
+#include <readdconflayer.hxx>
+#include <setnode.hxx>
+
+// component-data is encoded in dconf as follows:
+//
+// * The node hierarchy (starting at component nodes with names like
+//   "org.openoffice.Setup") maps to dconf paths underneath
+//   "/org/libreoffice/registry/".
+//
+// * Component, group, set, and localized property nodes map to dconf dirs
+//   (except for removal of set elements, see below), while property and
+//   localized value nodes map to dconf keys.
+//
+// * The names of nodes that are not set elements are used directly as dconf
+//   path segments.  (The syntax for node names is any non-empty sequences of
+//   any Unicode scalar values except U+0000--0008, U+000B--000C, U+000E--001F,
+//   U+002F SOLIDUS, and U+FFFE--FFFF.  TODO: "<aruiz> sberg, in general I think
+//   it'd be nice if you used path separators instead of dots though, they have
+//   meaning in dconf/gvdb world :-)"?)
+//
+// * Set element "fuse" and "replace" operations are encoded as dconf path
+//   segments as concatenations
+//
+//     N ; T ; O
+//
+//   where ";" represents U+003B SEMICOLON; N is an encoding of the node name,
+//   where each occurrence of U+003B SEMICOLON is replaced by the three
+//   characters "\3B" and each ocurrence of U+005C REVERSE SOLIDUS is replaced
+//   by the three characters "\5C"; T is an encoding of the full template name,
+//   where each occurrence of U+002F SOLIDUS is replaced by the three characters
+//   "\2F", each occurrence of U+003B SEMICOLON is replaced by the three
+//   characters "\3B", and each ocurrence of U+005C REVERSE SOLIDUS is replaced
+//   by the three characters "\5C"; and O is "fuse" or "replace", respectively.
+//
+// * Set element and property "remove" operations are encoded as dconf key path
+//   segments directly using the node name, and the associated value being a
+//   GVariant of empty tuple type.
+//
+// * Property and localized property value "fuse" operations map to GVariant
+//   instances as follows:
+//
+// ** Non-nillable boolean values map to GVariant boolean instances.
+//
+// ** Non-nillable short values map to GVariant int16 instances.
+//
+// ** Non-nillable int values map to GVariant int32 instances.
+//
+// ** Non-nillable long values map to GVariant int64 instances.
+//
+// ** Non-nillable double values map to GVariant double instances.
+//
+// ** Non-nillable string values map to GVariant string instances, with the
+//    following encoding: each occurrence of U+0000 NULL is replace by the three
+//    characters "\00" and each occurrence of U+005C REVERSE SOLIDUS is replaced
+//    by the three characters "\5C".
+//
+// ** Non-nillable hexbinary values map to GVariant byte array instances.
+//
+// ** Non-nillable list values recursively map to GVariant array instances.
+//
+// ** Nillable values recursively map to GVariant maybe instances.
+//
+// TODO: support "finalized", "mandatory", and "external"?
+
+namespace configmgr {
+
+namespace {
+
+template<typename T> class GObjectHolder {
+public:
+    explicit GObjectHolder(T * object): object_(object) {}
+
+    ~GObjectHolder() {
+        if (object_ != nullptr) {
+            g_object_unref(object_);
+        }
+    }
+
+    T * get() const { return object_; }
+
+private:
+    GObjectHolder(GObjectHolder &) = delete;
+    void operator =(GObjectHolder) = delete;
+
+    T * object_;
+};
+
+class GVariantHolder {
+public:
+    explicit GVariantHolder(GVariant * variant): variant_(variant) {}
+
+    ~GVariantHolder() { unref(); }
+
+    void reset(GVariant * variant) {
+        unref();
+        variant_ = variant;
+    }
+
+    GVariant * get() const { return variant_; }
+
+private:
+    GVariantHolder(GVariantHolder &) = delete;
+    void operator =(GVariantHolder) = delete;
+
+    void unref() {
+        if (variant_ != nullptr) {
+            g_variant_unref(variant_);
+        }
+    }
+
+    GVariant * variant_;
+};
+
+class StringArrayHolder {
+public:
+    explicit StringArrayHolder(gchar ** array): array_(array) {}
+
+    ~StringArrayHolder() { g_strfreev(array_); }
+
+    gchar ** get() const { return array_; }
+
+private:
+    StringArrayHolder(StringArrayHolder &) = delete;
+    void operator =(StringArrayHolder) = delete;
+
+    gchar ** array_;
+};
+
+bool decode(OUString * string, bool nul, bool slash, bool semicolon) {
+    for (sal_Int32 i = 0;; ++i) {
+        i = string->indexOf('\\', i);
+        if (i == -1) {
+            return true;
+        }
+        if (nul && string->match("00", i + 1)) {
+            *string = string->replaceAt(i, 3, OUString(sal_Unicode(0)));
+        } else if (slash && string->match("2F", i + 1)) {
+            *string = string->replaceAt(i, 3, "/");
+        } else if (semicolon && string->match("3B", i + 1)) {
+            *string = string->replaceAt(i, 3, ";");
+        } else if (string->match("5C", i + 1)) {
+            *string = string->replaceAt(i + 1, 2, "");
+        } else {
+            SAL_WARN("configmgr.dconf", "bad escape in " << *string);
+            return false;
+        }
+    }
+}
+
+bool getBoolean(
+    OString const & key, GVariantHolder const & variant, css::uno::Any * value)
+{
+    assert(value != nullptr);
+    if (!g_variant_is_of_type(variant.get(), G_VARIANT_TYPE_BOOLEAN)) {
+        SAL_WARN(
+            "configmgr.dconf",
+            "bad key " << key << " does not match boolean property");
+        return false;
+    }
+    *value <<= bool(g_variant_get_boolean(variant.get()));
+    return true;
+}
+
+bool getShort(
+    OString const & key, GVariantHolder const & variant, css::uno::Any * value)
+{
+    assert(value != nullptr);
+    if (!g_variant_is_of_type(variant.get(), G_VARIANT_TYPE_INT16)) {
+        SAL_WARN(
+            "configmgr.dconf",
+            "bad key " << key << " does not match short property");
+        return false;
+    }
+    *value <<= sal_Int16(g_variant_get_int16(variant.get()));
+    return true;
+}
+
+bool getInt(
+    OString const & key, GVariantHolder const & variant, css::uno::Any * value)
+{
+    assert(value != nullptr);
+    if (!g_variant_is_of_type(variant.get(), G_VARIANT_TYPE_INT32)) {
+        SAL_WARN(
+            "configmgr.dconf",
+            "bad key " << key << " does not match int property");
+        return false;
+    }
+    *value <<= sal_Int32(g_variant_get_int32(variant.get()));
+    return true;
+}
+
+bool getLong(
+    OString const & key, GVariantHolder const & variant, css::uno::Any * value)
+{
+    assert(value != nullptr);
+    if (!g_variant_is_of_type(variant.get(), G_VARIANT_TYPE_INT64)) {
+        SAL_WARN(
+            "configmgr.dconf",
+            "bad key " << key << " does not match long property");
+        return false;
+    }
+    *value <<= sal_Int64(g_variant_get_int64(variant.get()));
+    return true;
+}
+
+bool getDouble(
+    OString const & key, GVariantHolder const & variant, css::uno::Any * value)
+{
+    assert(value != nullptr);
+    if (!g_variant_is_of_type(variant.get(), G_VARIANT_TYPE_DOUBLE)) {
+        SAL_WARN(
+            "configmgr.dconf",
+            "bad key " << key << " does not match double property");
+        return false;
+    }
+    *value <<= double(g_variant_get_double(variant.get()));
+    return true;
+}
+
+bool getStringValue(
+    OString const & key, GVariantHolder const & variant, OUString * value)
+{
+    assert(value != nullptr);
+    if (!g_variant_is_of_type(variant.get(), G_VARIANT_TYPE_STRING)) {
+        SAL_WARN(
+            "configmgr.dconf",
+            "bad key " << key << " does not match string property");
+        return false;
+    }
+    gsize n;
+    char const * p = g_variant_get_string(variant.get(), &n);
+    if (n > static_cast<typename std::make_unsigned<sal_Int32>::type>(
+            std::numeric_limits<sal_Int32>::max()))
+    {
+        SAL_WARN("configmgr.dconf", "too long string value for key " << key);
+        return false;
+    }
+    if (!rtl_convertStringToUString(
+            &value->pData, p, static_cast<sal_Int32>(n), RTL_TEXTENCODING_UTF8,
+            (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
+             | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
+             | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
+    {
+        SAL_WARN("configmgr.dconf", "non--UTF-8 string value for key " << key);
+        return false;
+    }
+    return decode(value, true, false, false);
+}
+
+bool getString(
+    OString const & key, GVariantHolder const & variant, css::uno::Any * value)
+{
+    assert(value != nullptr);
+    OUString v;
+    if (!getStringValue(key, variant, &v)) {
+        return false;
+    }
+    *value <<= v;
+    return true;
+}
+
+bool getHexbinaryValue(
+    OString const & key, GVariantHolder const & variant,
+    css::uno::Sequence<sal_Int8> * value)
+{
+    assert(value != nullptr);
+    if (std::strcmp(g_variant_get_type_string(variant.get()), "ay") != 0) {
+        SAL_WARN(
+            "configmgr.dconf",
+            "bad key " << key << " does not match hexbinary property");
+        return false;
+    }
+    gsize n;
+    gconstpointer p = g_variant_get_fixed_array(
+        variant.get(), &n, sizeof (guchar));
+    if (n > static_cast<typename std::make_unsigned<sal_Int32>::type>(
+            std::numeric_limits<sal_Int32>::max()))
+    {
+        SAL_WARN("configmgr.dconf", "too long hexbinary value for key " << key);
+        return false;
+    }
+    value->realloc(static_cast<sal_Int32>(n));
+    static_assert(sizeof (sal_Int8) == sizeof (guchar), "size mismatch");
+    std::memcpy(value->getArray(), p, n * sizeof (guchar));
+        // assuming that n * sizeof (guchar) is small enough for std::size_t
+    return true;
+}
+
+bool getHexbinary(
+    OString const & key, GVariantHolder const & variant, css::uno::Any * value)
+{
+    assert(value != nullptr);
+    css::uno::Sequence<sal_Int8> v;
+    if (!getHexbinaryValue(key, variant, &v)) {
+        return false;
+    }
+    *value <<= v;
+    return true;
+}
+
+bool getBooleanList(
+    OString const & key, GVariantHolder const & variant, css::uno::Any * value)
+{
+    assert(value != nullptr);
+    if (std::strcmp(g_variant_get_type_string(variant.get()), "ab") != 0) {
+        SAL_WARN(
+            "configmgr.dconf",
+            "bad key " << key << " does not match boolean list property");
+        return false;
+    }
+    gsize n;
+    gconstpointer p = g_variant_get_fixed_array(
+        variant.get(), &n, sizeof (guchar));
+    if (n > static_cast<typename std::make_unsigned<sal_Int32>::type>(
+            std::numeric_limits<sal_Int32>::max()))
+    {
+        SAL_WARN("configmgr.dconf", "too long boolean list for key " << key);
+        return false;
+    }
+    css::uno::Sequence<sal_Bool> v(static_cast<sal_Int32>(n));
+    static_assert(sizeof (sal_Bool) == sizeof (guchar), "size mismatch");
+    std::memcpy(v.getArray(), p, n * sizeof (guchar));
+        // assuming that n * sizeof (guchar) is small enough for std::size_t
+    *value <<= v;
+    return true;
+}
+
+bool getShortList(
+    OString const & key, GVariantHolder const & variant, css::uno::Any * value)
+{
+    assert(value != nullptr);
+    if (std::strcmp(g_variant_get_type_string(variant.get()), "an") != 0) {
+        SAL_WARN(
+            "configmgr.dconf",
+            "bad key " << key << " does not match short list property");
+        return false;
+    }
+    gsize n;
+    gconstpointer p = g_variant_get_fixed_array(
+        variant.get(), &n, sizeof (gint16));
+    if (n > static_cast<typename std::make_unsigned<sal_Int32>::type>(
+            std::numeric_limits<sal_Int32>::max()))
+    {
+        SAL_WARN("configmgr.dconf", "too long short list for key " << key);
+        return false;
+    }
+    css::uno::Sequence<sal_Int16> v(static_cast<sal_Int32>(n));
+    static_assert(sizeof (sal_Int16) == sizeof (gint16), "size mismatch");
+    std::memcpy(v.getArray(), p, n * sizeof (gint16));
+        // assuming that n * sizeof (gint16) is small enough for std::size_t
+    *value <<= v;
+    return true;
+}
+
+bool getIntList(
+    OString const & key, GVariantHolder const & variant, css::uno::Any * value)
+{
+    assert(value != nullptr);
+    if (std::strcmp(g_variant_get_type_string(variant.get()), "ai") != 0) {
+        SAL_WARN(
+            "configmgr.dconf",
+            "bad key " << key << " does not match int list property");
+        return false;
+    }
+    gsize n;
+    gconstpointer p = g_variant_get_fixed_array(
+        variant.get(), &n, sizeof (gint32));
+    if (n > static_cast<typename std::make_unsigned<sal_Int32>::type>(
+            std::numeric_limits<sal_Int32>::max()))
+    {
+        SAL_WARN("configmgr.dconf", "too long int list for key " << key);
+        return false;
+    }
+    css::uno::Sequence<sal_Int32> v(static_cast<sal_Int32>(n));
+    static_assert(sizeof (sal_Int32) == sizeof (gint32), "size mismatch");
+    std::memcpy(v.getArray(), p, n * sizeof (gint32));
+        // assuming that n * sizeof (gint32) is small enough for std::size_t
+    *value <<= v;
+    return true;
+}
+
+bool getLongList(
+    OString const & key, GVariantHolder const & variant, css::uno::Any * value)
+{
+    assert(value != nullptr);
+    if (std::strcmp(g_variant_get_type_string(variant.get()), "ax") != 0) {
+        SAL_WARN(
+            "configmgr.dconf",
+            "bad key " << key << " does not match long list property");
+        return false;
+    }
+    gsize n;
+    gconstpointer p = g_variant_get_fixed_array(
+        variant.get(), &n, sizeof (gint64));
+    if (n > static_cast<typename std::make_unsigned<sal_Int32>::type>(
+            std::numeric_limits<sal_Int32>::max()))
+    {
+        SAL_WARN("configmgr.dconf", "too long long list for key " << key);
+        return false;
+    }
+    css::uno::Sequence<sal_Int64> v(static_cast<sal_Int32>(n));
+    static_assert(sizeof (sal_Int64) == sizeof (gint64), "size mismatch");
+    std::memcpy(v.getArray(), p, n * sizeof (gint64));
+        // assuming that n * sizeof (gint64) is small enough for std::size_t
+    *value <<= v;
+    return true;
+}
+
+bool getDoubleList(
+    OString const & key, GVariantHolder const & variant, css::uno::Any * value)
+{
+    assert(value != nullptr);
+    if (std::strcmp(g_variant_get_type_string(variant.get()), "ad") != 0) {
+        SAL_WARN(
+            "configmgr.dconf",
+            "bad key " << key << " does not match double list property");
+        return false;
+    }
+    gsize n;
+    gconstpointer p = g_variant_get_fixed_array(
+        variant.get(), &n, sizeof (gdouble));
+    if (n > static_cast<typename std::make_unsigned<sal_Int32>::type>(
+            std::numeric_limits<sal_Int32>::max()))
+    {
+        SAL_WARN("configmgr.dconf", "too long double list for key " << key);
+        return false;
+    }
+    css::uno::Sequence<double> v(static_cast<sal_Int32>(n));
+    static_assert(std::is_same<double, gdouble>::value, "type mismatch");
+    std::memcpy(v.getArray(), p, n * sizeof (gdouble));
+        // assuming that n * sizeof (gdouble) is small enough for std::size_t
+    *value <<= v;
+    return true;
+}
+
+bool getStringList(
+    OString const & key, GVariantHolder const & variant, css::uno::Any * value)
+{
+    assert(value != nullptr);
+    if (std::strcmp(g_variant_get_type_string(variant.get()), "as") != 0) {
+        SAL_WARN(
+            "configmgr.dconf",
+            "bad key " << key << " does not match string list property");
+        return false;
+    }
+    gsize n = g_variant_n_children(variant.get());
+    if (n > static_cast<typename std::make_unsigned<sal_Int32>::type>(
+            std::numeric_limits<sal_Int32>::max()))
+    {
+        SAL_WARN("configmgr.dconf", "too long string list for key " << key);
+        return false;
+    }
+    css::uno::Sequence<OUString> v(static_cast<sal_Int32>(n));
+    for (gsize i = 0; i != n; ++i) {
+        GVariantHolder c(g_variant_get_child_value(variant.get(), i));
+        if (!getStringValue(key, c, v.getArray() + i)) {
+            return false;
+        }
+    }
+    *value <<= v;
+    return true;
+}
+
+bool getHexbinaryList(
+    OString const & key, GVariantHolder const & variant, css::uno::Any * value)
+{
+    assert(value != nullptr);
+    if (std::strcmp(g_variant_get_type_string(variant.get()), "aay") != 0) {
+        SAL_WARN(
+            "configmgr.dconf",
+            "bad key " << key << " does not match hexbinary list property");
+        return false;
+    }
+    gsize n = g_variant_n_children(variant.get());
+    if (n > static_cast<typename std::make_unsigned<sal_Int32>::type>(
+            std::numeric_limits<sal_Int32>::max()))
+    {
+        SAL_WARN("configmgr.dconf", "too long hexbinary list for key " << key);
+        return false;
+    }
+    css::uno::Sequence<css::uno::Sequence<sal_Int8>> v(
+        static_cast<sal_Int32>(n));
+    for (gsize i = 0; i != n; ++i) {
+        GVariantHolder c(g_variant_get_child_value(variant.get(), i));
+        if (!getHexbinaryValue(key, c, v.getArray() + i)) {
+            return false;
+        }
+    }
+    *value <<= v;
+    return true;
+}
+
+bool getAny(
+    OString const & key, GVariantHolder const & variant, css::uno::Any * value)
+{
+    char const * t = g_variant_get_type_string(variant.get());
+    if (std::strcmp(t, "b") == 0) {
+        return getBoolean(key, variant, value);
+    }
+    if (std::strcmp(t, "n") == 0) {
+        return getShort(key, variant, value);
+    }
+    if (std::strcmp(t, "i") == 0) {
+        return getInt(key, variant, value);
+    }
+    if (std::strcmp(t, "x") == 0) {
+        return getLong(key, variant, value);
+    }
+    if (std::strcmp(t, "d") == 0) {
+        return getDouble(key, variant, value);
+    }
+    if (std::strcmp(t, "s") == 0) {
+        return getString(key, variant, value);
+    }
+    if (std::strcmp(t, "ay") == 0) {
+        return getHexbinary(key, variant, value);
+    }
+    if (std::strcmp(t, "ab") == 0) {
+        return getBooleanList(key, variant, value);
+    }
+    if (std::strcmp(t, "an") == 0) {
+        return getShortList(key, variant, value);
+    }
+    if (std::strcmp(t, "ai") == 0) {
+        return getIntList(key, variant, value);
+    }
+    if (std::strcmp(t, "ax") == 0) {
+        return getLongList(key, variant, value);
+    }
+    if (std::strcmp(t, "ad") == 0) {
+        return getDoubleList(key, variant, value);
+    }
+    if (std::strcmp(t, "as") == 0) {
+        return getStringList(key, variant, value);
+    }
+    if (std::strcmp(t, "aay") == 0) {
+        return getHexbinaryList(key, variant, value);
+    }
+    SAL_WARN(
+        "configmgr.dconf", "bad key " << key << " does not match any property");
+    return false;
+}
+
+enum class ReadValue { Error, Value, Remove };
+
+ReadValue readValue(
+    GObjectHolder<DConfClient> const & client, OString const & path, Type type,
+    bool nillable, bool removable, css::uno::Any * value)
+{
+    assert(value != nullptr);
+    assert(!value->hasValue());
+    assert(!path.endsWith("/"));
+    GVariantHolder v(dconf_client_read(client.get(), path.getStr()));
+    if (v.get() == nullptr) {
+        SAL_WARN("configmgr.dconf", "cannot read key " << path);
+        return ReadValue::Error;
+    }
+    if (removable && std::strcmp(g_variant_get_type_string(v.get()), "()") == 0)
+    {
+        return ReadValue::Remove;
+    }
+    bool nil;
+    if (nillable) {
+        if (g_variant_classify(v.get()) != G_VARIANT_CLASS_MAYBE) {
+            SAL_WARN(
+                "configmgr.dconf",
+                "bad key " << path << " does not match nillable property");
+        }
+        v.reset(g_variant_get_maybe(v.get()));
+        nil = v.get() == nullptr;
+    } else {
+        nil = false;
+    }
+    if (!nil) {
+        switch (type) {
+        case TYPE_ANY:
+            if (!getAny(path, v, value)) {
+                return ReadValue::Error;
+            }
+            break;
+        case TYPE_BOOLEAN:
+            if (!getBoolean(path, v, value)) {
+                return ReadValue::Error;
+            }
+            break;
+        case TYPE_SHORT:
+            if (!getShort(path, v, value)) {
+                return ReadValue::Error;
+            }
+            break;
+        case TYPE_INT:
+            if (!getInt(path, v, value)) {
+                return ReadValue::Error;
+            }
+            break;
+        case TYPE_LONG:
+            if (!getLong(path, v, value)) {
+                return ReadValue::Error;
+            }
+            break;
+        case TYPE_DOUBLE:
+            if (!getDouble(path, v, value)) {
+                return ReadValue::Error;
+            }
+            break;
+        case TYPE_STRING:
+            if (!getString(path, v, value)) {
+                return ReadValue::Error;
+            }
+            break;
+        case TYPE_HEXBINARY:
+            if (!getHexbinary(path, v, value)) {
+                return ReadValue::Error;
+            }
+            break;
+        case TYPE_BOOLEAN_LIST:
+            if (!getBooleanList(path, v, value)) {
+                return ReadValue::Error;
+            }
+            break;
+        case TYPE_SHORT_LIST:
+            if (!getShortList(path, v, value)) {
+                return ReadValue::Error;
+            }
+            break;
+        case TYPE_INT_LIST:
+            if (!getIntList(path, v, value)) {
+                return ReadValue::Error;
+            }
+            break;
+        case TYPE_LONG_LIST:
+            if (!getLongList(path, v, value)) {
+                return ReadValue::Error;
+            }
+            break;
+        case TYPE_DOUBLE_LIST:
+            if (!getDoubleList(path, v, value)) {
+                return ReadValue::Error;
+            }
+            break;
+        case TYPE_STRING_LIST:
+            if (!getStringList(path, v, value)) {
+                return ReadValue::Error;
+            }
+            break;
+        case TYPE_HEXBINARY_LIST:
+            if (!getHexbinaryList(path, v, value)) {
+                return ReadValue::Error;
+            }
+            break;
+        default:
+            assert(false); // cannot happen
+        }
+    }
+    return ReadValue::Value;
+}
+
+void readDir(
+    Data & data, int layer, rtl::Reference<Node> const & node,
+    NodeMap & members, GObjectHolder<DConfClient> const & client,
+    OString const & dir)
+{
+    StringArrayHolder a(dconf_client_list(client.get(), dir.getStr(), nullptr));
+    for (char const * const * p = a.get(); *p != nullptr; ++p) {
+        std::size_t n = std::strlen(*p);
+        if (n > static_cast<typename std::make_unsigned<sal_Int32>::type>(
+                std::numeric_limits<sal_Int32>::max()))
+        {
+            SAL_WARN("configmgr.dconf", "too long dir/key in dir " << dir);
+            continue;
+        }
+        OString s(*p, static_cast<sal_Int32>(n));
+        OString path(dir + s);
+        OUString seg;
+        if (!rtl_convertStringToUString(
+                &seg.pData, s.getStr(), s.getLength(), RTL_TEXTENCODING_UTF8,
+                (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
+                 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
+                 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
+        {
+            SAL_WARN("configmgr.dconf", "non--UTF-8 dir/key in dir " << dir);
+            continue;
+        }
+        bool isDir = seg.endsWith("/", &seg);
+        bool remove;
+        OUString name;
+        OUString templ;
+        bool replace;
+        if (node.is() && node->kind() == Node::KIND_SET) {
+            if (isDir) {
+                remove = false;
+                sal_Int32 i1 = seg.indexOf(';');
+                if (i1 == -1) {
+                    SAL_WARN(
+                        "configmgr.dconf", "bad set element syntax " << path);
+                    continue;
+                }
+                name = seg.copy(0, i1);
+                if (!decode(&name, false, false, true)) {
+                    continue;
+                }
+                ++i1;
+                sal_Int32 i2 = seg.indexOf(';', i1);
+                if (i2 == -1) {
+                    SAL_WARN(
+                        "configmgr.dconf", "bad set element syntax " << path);
+                    continue;
+                }
+                templ = seg.copy(i1, i2 - i1);
+                if (!decode(&templ, false, true, true)) {
+                    continue;
+                }
+                ++i2;
+                if (rtl_ustr_asciil_reverseCompare_WithLength(
+                        seg.getStr() + i2, seg.getLength() - i2, "fuse",
+                        std::strlen("fuse"))
+                    == 0)
+                {
+                    replace = false;
+                } else if (rtl_ustr_asciil_reverseCompare_WithLength(
+                               seg.getStr() + i2, seg.getLength() - i2,
+                               "replace", std::strlen("replace"))
+                           == 0)
+                {
+                    replace = true;
+                } else {
+                    SAL_WARN(
+                        "configmgr.dconf", "bad set element syntax " << path);
+                    continue;
+                }
+                rtl::Reference<SetNode> set(static_cast<SetNode *>(node.get()));
+                if (!set->isValidTemplate(templ)) {
+                    SAL_WARN(
+                        "configmgr.dconf",
+                        "bad " << path
+                            << " denotes unsupported set element template");
+                    continue;
+                }
+            } else {
+                remove = true;
+                name = seg;
+                replace = false;
+                assert(!path.endsWith("/"));
+                GVariantHolder v(
+                    dconf_client_read(client.get(), path.getStr()));
+                if (v.get() == nullptr) {
+                    SAL_WARN("configmgr.dconf", "cannot read key " << path);
+                    continue;
+                }
+                if (std::strcmp(g_variant_get_type_string(v.get()), "()") != 0)
+                {
+                    SAL_WARN(
+                        "configmgr.dconf",
+                        "bad " << path
+                            << " does not denote set element removal");
+                    continue;
+                }
+            }
+        } else {
+            remove = false;
+            name = seg;
+            replace = false;
+        }
+        rtl::Reference<Node> member(members.findNode(layer, name));
+        bool insert = !member.is();
+        if (!remove && (replace || insert)) {
+            if (!node.is()) {
+                SAL_WARN("configmgr.dconf", "bad unmatched " << path);
+                continue;
+            }
+            switch (node->kind()) {
+            case Node::KIND_LOCALIZED_PROPERTY:
+                member.set(new LocalizedValueNode(layer));
+                break;
+            case Node::KIND_GROUP:
+                if (!static_cast<GroupNode *>(node.get())->isExtensible()) {
+                    SAL_WARN("configmgr.dconf", "bad unmatched " << path);
+                    continue;
+                }
+                member.set(
+                    new PropertyNode(
+                        layer, TYPE_ANY, true, css::uno::Any(), true));
+                break;
+            case Node::KIND_SET:
+                assert(!templ.isEmpty());
+                member = data.getTemplate(layer, templ);
+                if (!member.is()) {
+                    SAL_WARN(
+                        "configmgr.dconf",
+                        "bad " << path << " denoting undefined template "
+                            << templ);
+                    continue;
+                }
+                break;
+            default:
+                assert(false); // cannot happen
+            }
+        } else if (!(templ.isEmpty()
+                     || (node.is() && templ == node->getTemplateName())))
+        {
+            SAL_WARN(
+                "configmgr.dconf",
+                "bad " << path
+                    << " denoting set element of non-matching template "
+                    << node->getTemplateName());
+            continue;
+        }
+        if (member->getFinalized() < layer) {
+            continue;
+        }
+        switch (member->kind()) {
+        case Node::KIND_PROPERTY:
+            {
+                if (isDir) {
+                    SAL_WARN(
+                        "configmgr.dconf",
+                        "bad dir " << path << " does not match property");
+                    continue;
+                }
+                rtl::Reference<PropertyNode> prop(
+                    static_cast<PropertyNode *>(member.get()));
+                css::uno::Any value;
+                switch (readValue(
+                            client, path, prop->getStaticType(),
+                            prop->isNillable(), prop->isExtension(), &value))
+                {
+                case ReadValue::Error:
+                    continue;
+                case ReadValue::Value:
+                    prop->setValue(layer, value);
+                    break;
+                case ReadValue::Remove:
+                    remove = true;
+                    break;
+                }
+                break;
+            }
+        case Node::KIND_LOCALIZED_VALUE:
+            {
+                if (isDir) {
+                    SAL_WARN(
+                        "configmgr.dconf",
+                        "bad dir " << path
+                            << " does not match localized value");
+                    continue;
+                }
+                assert(
+                    node.is() && node->kind() == Node::KIND_LOCALIZED_PROPERTY);
+                rtl::Reference<LocalizedPropertyNode> locProp(
+                    static_cast<LocalizedPropertyNode *>(node.get()));
+                css::uno::Any value;
+                if (readValue(
+                        client, path, locProp->getStaticType(),
+                        locProp->isNillable(), false, &value)
+                    == ReadValue::Error)
+                {
+                    continue;
+                }
+                static_cast<LocalizedValueNode *>(member.get())->setValue(
+                    layer, value);
+                break;
+            }
+        case Node::KIND_LOCALIZED_PROPERTY:
+        case Node::KIND_GROUP:
+        case Node::KIND_SET:
+            if (!isDir) {
+                SAL_WARN(
+                    "configmgr.dconf",
+                    "bad key " << path
+                        << " does not match localized property, group, or set,"
+                        " respectively");
+                continue;
+            }
+            assert(path.endsWith("/"));
+            readDir(data, layer, member, member->getMembers(), client, path);
+            break;
+        default:
+            assert(false); // cannot happen
+        }
+        if (remove) {
+            if (!member->getMandatory()) {
+                members.erase(name);
+            }
+        } else if (replace) {
+            members.erase(name);
+            members.insert(NodeMap::value_type(name, member));
+        } else if (insert) {
+            members.insert(NodeMap::value_type(name, member));
+        }
+    }
+}
+
+}
+
+void readDconfLayer(Data & data, int layer) {
+    GObjectHolder<DConfClient> client(dconf_client_new());
+    readDir(
+        data, layer, rtl::Reference<Node>(), data.getComponents(), client,
+        "/org/libreoffice/registry/");
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/configmgr/source/readdconflayer.hxx b/configmgr/source/readdconflayer.hxx
new file mode 100644
index 0000000..63a4698
--- /dev/null
+++ b/configmgr/source/readdconflayer.hxx
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_READDCONFLAYER_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_READDCONFLAYER_HXX
+
+#include <sal/config.h>
+
+namespace configmgr { struct Data; }
+
+namespace configmgr {
+
+void readDconfLayer(Data & data, int layer);
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/configure.ac b/configure.ac
index d061912..aaf1d6a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1475,6 +1475,11 @@ AC_ARG_ENABLE(collada,
     AS_HELP_STRING([--disable-collada],
         [Disable collada support (Rendering 3D models stored in *.dae and *.kmz format).]))
 
+AC_ARG_ENABLE(dconf,
+    AS_HELP_STRING([--disable-dconf],
+        [Disable the dconf configuration backend (enabled by default where
+         available).]))
+
 dnl ===================================================================
 dnl Optional Packages (--with/without-)
 dnl ===================================================================
@@ -10493,6 +10498,29 @@ AC_SUBST([COLLADA2GLTF_CFLAGS])
 AC_SUBST([COLLADA2GLTF_LIBS])
 AC_SUBST([SYSTEM_COLLADA2GLTF])
 
+if test "$enable_dconf" != no; then
+    PKG_CHECK_MODULES([DCONF], [dconf], [], [
+        if test "$enable_dconf" = yes; then
+            AC_MSG_ERROR([dconf not found])
+        else
+            enable_dconf=no
+        fi])
+fi
+AC_MSG_CHECKING([whether to enable dconf])
+if test "$enable_dconf" = no; then
+    DCONF_CFLAGS=
+    DCONF_LIBS=
+    ENABLE_DCONF=
+    AC_MSG_RESULT([no])
+else
+    ENABLE_DCONF=TRUE
+    AC_DEFINE(ENABLE_DCONF)
+    AC_MSG_RESULT([yes])
+fi
+AC_SUBST([DCONF_CFLAGS])
+AC_SUBST([DCONF_LIBS])
+AC_SUBST([ENABLE_DCONF])
+
 # pdf import?
 AC_MSG_CHECKING([whether to build the PDF import feature])
 ENABLE_PDFIMPORT=
@@ -13112,6 +13140,7 @@ AC_CONFIG_FILES([config_host.mk
                  ios/lo.xcconfig])
 AC_CONFIG_HEADERS([config_host/config_buildid.h])
 AC_CONFIG_HEADERS([config_host/config_clang.h])
+AC_CONFIG_HEADERS([config_host/config_dconf.h])
 AC_CONFIG_HEADERS([config_host/config_eot.h])
 AC_CONFIG_HEADERS([config_host/config_extension_update.h])
 AC_CONFIG_HEADERS([config_host/config_cairo_canvas.h])
diff --git a/distro-configs/LibreOfficeLinux.conf b/distro-configs/LibreOfficeLinux.conf
index 7c21ce7..2824fb6 100644
--- a/distro-configs/LibreOfficeLinux.conf
+++ b/distro-configs/LibreOfficeLinux.conf
@@ -33,6 +33,7 @@
 --enable-epm
 --enable-python=internal
 --enable-online-update
+--disable-dconf
 --disable-gio
 --disable-randr-link
 --disable-kde4
diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox
index d734876..70f3456 100644
--- a/include/sal/log-areas.dox
+++ b/include/sal/log-areas.dox
@@ -491,6 +491,7 @@ certain functionality.
 @li @c basebmp
 @li @c binaryurp
 @li @c configmgr
+ at li @c configmgr.dconf
 @li @c cppcanvas
 @li @c cppcanvas.emf
 @li @c drawinglayer
diff --git a/instsetoo_native/CustomTarget_setup.mk b/instsetoo_native/CustomTarget_setup.mk
index 4217424..dd331af 100644
--- a/instsetoo_native/CustomTarget_setup.mk
+++ b/instsetoo_native/CustomTarget_setup.mk
@@ -48,7 +48,7 @@ $(call gb_CustomTarget_get_workdir,instsetoo_native/setup)/$(call gb_Helper_get_
 		&& echo 'BRAND_BASE_DIR=$${ORIGIN}/..' \
 		&& echo 'BRAND_INI_DIR=$${ORIGIN}' \
 		&& echo 'BRAND_SHARE_SUBDIR=$(LIBO_SHARE_FOLDER)' \
-		&& echo 'CONFIGURATION_LAYERS=xcsxcu:$${BRAND_BASE_DIR}/$(LIBO_SHARE_FOLDER)/registry res:$${BRAND_BASE_DIR}/$(LIBO_SHARE_FOLDER)/registry $(if $(filter WNT,$(OS)),winreg: )bundledext:$${$${BRAND_BASE_DIR}/$(LIBO_ETC_FOLDER)/$(call gb_Helper_get_rcfile,louno):BUNDLED_EXTENSIONS_USER}/registry/com.sun.star.comp.deployment.configuration.PackageRegistryBackend/configmgr.ini sharedext:$${$${BRAND_BASE_DIR}/$(LIBO_ETC_FOLDER)/$(call gb_Helper_get_rcfile,louno):SHARED_EXTENSIONS_USER}/registry/com.sun.star.comp.deployment.configuration.PackageRegistryBackend/configmgr.ini userext:$${$${BRAND_BASE_DIR}/$(LIBO_ETC_FOLDER)/$(call gb_Helper_get_rcfile,louno):UNO_USER_PACKAGES_CACHE}/registry/com.sun.star.comp.deployment.configuration.PackageRegistryBackend/configmgr.ini user:$${$$BRAND_BASE_DIR/$(LIBO_ETC_FOLDER)/$(call gb_Helper_get_rcfile,bootstrap):UserInstallation}/user/registrymodifications.xcu' \
+		&& echo 'CONFIGURATION_LAYERS=xcsxcu:$${BRAND_BASE_DIR}/$(LIBO_SHARE_FOLDER)/registry res:$${BRAND_BASE_DIR}/$(LIBO_SHARE_FOLDER)/registry  $(if $(ENABLE_DCONF),dconf: )$(if $(filter WNT,$(OS)),winreg: )bundledext:$${$${BRAND_BASE_DIR}/$(LIBO_ETC_FOLDER)/$(call gb_Helper_get_rcfile,louno):BUNDLED_EXTENSIONS_USER}/registry/com.sun.star.comp.deployment.configuration.PackageRegistryBackend/configmgr.ini sharedext:$${$${BRAND_BASE_DIR}/$(LIBO_ETC_FOLDER)/$(call gb_Helper_get_rcfile,louno):SHARED_EXTENSIONS_USER}/registry/com.sun.star.comp.deployment.configuration.PackageRegistryBackend/configmgr.ini userext:$${$${BRAND_BASE_DIR}/$(LIBO_ETC_FOLDER)/$(call gb_Helper_get_rcfile,louno):UNO_USER_PACKAGES_CACHE}/registry/com.sun.star.comp.deployment.configuration.PackageRegistryBackend/configmgr.ini user:$${$$BRAND_BASE_DIR/$(LIBO_ETC_FOLDER)/$(call gb_Helper_get_rcfile,bootstrap):UserInstallation}/user/registrymodifications.xcu' \
 		&& echo 'LO_JAVA_DIR=$${BRAND_BASE_DIR}/$(LIBO_SHARE_JAVA_FOLDER)' \
 		&& echo 'LO_LIB_DIR=$${BRAND_BASE_DIR}/$(LIBO_LIB_FOLDER)' \
 		&& echo 'BAK_EXTENSIONS=$${$$ORIGIN/$(call gb_Helper_get_rcfile,louno):TMP_EXTENSIONS}' \
diff --git a/scp2/source/ooo/common_brand.scp b/scp2/source/ooo/common_brand.scp
index e79dab7..6bf7b30 100644
--- a/scp2/source/ooo/common_brand.scp
+++ b/scp2/source/ooo/common_brand.scp
@@ -29,6 +29,7 @@
 
 #include "AutoInstall/brand"
 
+#include "config_dconf.h"
 #include "config_folders.h"
 
 Module gid_Module_Root_Brand
@@ -1117,17 +1118,25 @@ ProfileItem gid_Brand_Profileitem_Fundamental_Ure_Bin_Dir
     Value = "${BRAND_BASE_DIR}/" LIBO_URE_BIN_FOLDER;
 End
 
+#if ENABLE_DCONF
+#define CONFIGURATION_LAYERS_DCONF " dconf:"
+#else
+#define CONFIGURATION_LAYERS_DCONF
+#endif
+#if defined WNT
+#define CONFIGURATION_LAYERS_WINREG " winreg:"
+#else
+#define CONFIGURATION_LAYERS_WINREG
+#endif
 ProfileItem gid_Brand_Profileitem_Fundamental_Configuration_Layers
     ProfileID = gid_Brand_Profile_Fundamental_Ini;
     ModuleID = gid_Module_Root_Brand;
     Section = "Bootstrap";
     Key = "CONFIGURATION_LAYERS";
-#if defined WNT
-    Value = "xcsxcu:${BRAND_BASE_DIR}/" LIBO_SHARE_FOLDER "/registry res:${BRAND_BASE_DIR}/" LIBO_SHARE_FOLDER "/registry winreg: bundledext:${${BRAND_BASE_DIR}/" LIBO_ETC_FOLDER "/" PROFILENAME(louno) ":BUNDLED_EXTENSIONS_USER}/registry/com.sun.star.comp.deployment.configuration.PackageRegistryBackend/configmgr.ini sharedext:${${BRAND_BASE_DIR}/" LIBO_ETC_FOLDER "/" PROFILENAME(louno) ":SHARED_EXTENSIONS_USER}/registry/com.sun.star.comp.deployment.configuration.PackageRegistryBackend/configmgr.ini userext:${${BRAND_BASE_DIR}/" LIBO_ETC_FOLDER "/" PROFILENAME(louno) ":UNO_USER_PACKAGES_CACHE}/registry/com.sun.star.comp.deployment.configuration.PackageRegistryBackend/configmgr.ini user:${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" PROFILENAME(bootstrap) ":UserInstallation}/user/registrymodifications.xcu";
-#else
-    Value = "xcsxcu:${BRAND_BASE_DIR}/" LIBO_SHARE_FOLDER "/registry res:${BRAND_BASE_DIR}/" LIBO_SHARE_FOLDER "/registry bundledext:${${BRAND_BASE_DIR}/" LIBO_ETC_FOLDER "/" PROFILENAME(louno) ":BUNDLED_EXTENSIONS_USER}/registry/com.sun.star.comp.deployment.configuration.PackageRegistryBackend/configmgr.ini sharedext:${${BRAND_BASE_DIR}/" LIBO_ETC_FOLDER "/" PROFILENAME(louno) ":SHARED_EXTENSIONS_USER}/registry/com.sun.star.comp.deployment.configuration.PackageRegistryBackend/configmgr.ini userext:${${BRAND_BASE_DIR}/" LIBO_ETC_FOLDER "/" PROFILENAME(louno) ":UNO_USER_PACKAGES_CACHE}/registry/com.sun.star.comp.deployment.configuration.PackageRegistryBackend/configmgr.ini user:${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" PROFILENAME(bootstrap) ":UserInstallation}/user/registrymodifications.xcu";
-#endif
+    Value = "xcsxcu:${BRAND_BASE_DIR}/" LIBO_SHARE_FOLDER "/registry res:${BRAND_BASE_DIR}/" LIBO_SHARE_FOLDER "/registry" CONFIGURATION_LAYERS_WINREG " bundledext:${${BRAND_BASE_DIR}/" LIBO_ETC_FOLDER "/" PROFILENAME(louno) ":BUNDLED_EXTENSIONS_USER}/registry/com.sun.star.comp.deployment.configuration.PackageRegistryBackend/configmgr.ini sharedext:${${BRAND_BASE_DIR}/" LIBO_ETC_FOLDER "/" PROFILENAME(louno) ":SHARED_EXTENSIONS_USER}/registry/com.sun.star.comp.deployment.configuration.PackageRegistryBackend/configmgr.ini userext:${${BRAND_BASE_DIR}/" LIBO_ETC_FOLDER "/" PROFILENAME(louno) ":UNO_USER_PACKAGES_CACHE}/registry/com.sun.star.comp.deployment.configuration.PackageRegistryBackend/configmgr.ini user:${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" PROFILENAME(bootstrap) ":UserInstallation}/user/registrymodifications.xcu";
 End
+#undef CONFIGURATION_LAYERS_DCONF
+#undef CONFIGURATION_LAYERS_WINREG
 
 #if !defined MACOSX
 ProfileItem gid_Brand_Profileitem_Redirect_Ure_Bootstrap


More information about the Libreoffice-commits mailing list