File 0002-Bug-259356-Add-support-for-the-XDG-Base-Directory-Specification.diff of Package firefox-xdg

diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -3455,5 +3455,12 @@
 pref("browser.ipProtection.log", false);
 pref("browser.ipProtection.guardian.endpoint", "https://vpn.mozilla.org/");
 
 // Pref to enable aboug:glean redesign.
 pref("about.glean.redesign.enabled", false);
+
+// A preference that will be locked to reflect whether this build has support
+// for XDG Config Home handling. Mostly used to be able to keep tests around
+// in case of a backout of the feature
+#if defined(MOZ_WIDGET_GTK)
+pref("widget.support-xdg-config", true, locked);
+#endif
diff --git a/toolkit/moz.configure b/toolkit/moz.configure
--- a/toolkit/moz.configure
+++ b/toolkit/moz.configure
@@ -3818,11 +3818,13 @@
 
     @depends(target)
     def default_user_appdir(target):
         if target.kernel in ("WINNT", "Darwin"):
             return "Mozilla"
-        return ".mozilla"
+        elif target.os == "Android":
+            return ".mozilla"
+        return "mozilla"
 
     option(
         "--with-user-appdir",
         nargs=1,
         default=default_user_appdir,
@@ -3835,11 +3837,16 @@
             die("--without-user-appdir is not a valid option.")
         if "/" in appdir[0]:
             die("--with-user-appdir must be a single relative path.")
         return '"{}"'.format(appdir[0])
 
+    @depends("--with-user-appdir")
+    def forced_or_dotted_user_appdir(value):
+        return value.origin != "default" or value[0].startswith(".")
+
     set_define("MOZ_USER_DIR", user_appdir)
+    set_define("MOZ_LEGACY_HOME", True, when=forced_or_dotted_user_appdir)
 
 
 # Check for sin_len and sin6_len - used by SCTP; only appears in Mac/*BSD generally
 # ==============================================================
 with only_when(compile_environment):
diff --git a/toolkit/xre/nsXREDirProvider.h b/toolkit/xre/nsXREDirProvider.h
--- a/toolkit/xre/nsXREDirProvider.h
+++ b/toolkit/xre/nsXREDirProvider.h
@@ -68,10 +68,29 @@
     return GetUserDataDirectory(aFile, true);
   }
 
   static nsresult GetUserDataDirectory(nsIFile** aFile, bool aLocal);
 
+#if defined(MOZ_WIDGET_GTK)
+  static nsresult GetLegacyOrXDGEnvValue(const char* aHomeDir,
+                                         const char* aEnvName,
+                                         nsCString aSubdir, nsIFile** aFile);
+  static nsresult GetLegacyOrXDGCachePath(const char* aHomeDir,
+                                          nsIFile** aFile);
+  static nsresult GetLegacyOrXDGHomePath(const char* aHomeDir, nsIFile** aFile,
+                                         bool aForceLegacy = false);
+  static nsresult AppendFromAppData(nsIFile* aFile, bool aIsDotted);
+
+  static bool IsForceLegacyHome();
+
+  static bool LegacyHomeExists(nsIFile** aFile);
+
+  static nsresult GetLegacyOrXDGConfigHome(const char* aHomeDir,
+                                           nsIFile** aFile);
+
+#endif  // defined(MOZ_WIDGET_GTK)
+
   /* make sure you clone it, if you need to do stuff to it */
   nsIFile* GetGREDir() { return mGREDir; }
   nsIFile* GetGREBinDir() { return mGREBinDir; }
   nsIFile* GetAppDir() {
     if (mXULAppDir) return mXULAppDir;
@@ -116,11 +135,17 @@
       nsCOMPtr<nsIFile>& aLocal, nsCOMPtr<nsIFile>& aGlobal);
 
  private:
   nsresult GetFilesInternal(const char* aProperty,
                             nsISimpleEnumerator** aResult);
-  static nsresult GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal);
+
+  // aForceLegacy will only act on !aLocal and make sure the path returned
+  // is directly under $HOME. Useful for UserNativeManifests and
+  // SysUserExtensionDir to keep legacy behavior with XDG support active.
+  static nsresult GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal,
+                                           bool aForceLegacy = false);
+  static nsresult GetNativeUserManifestsDirectory(nsIFile** aFile);
   static nsresult GetSysUserExtensionsDirectory(nsIFile** aFile);
 #if defined(XP_UNIX) || defined(XP_MACOSX)
   static nsresult GetSystemExtensionsDirectory(nsIFile** aFile);
 #endif
   static nsresult EnsureDirectoryExists(nsIFile* aDirectory);
diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -10,10 +10,11 @@
 #endif
 
 #include "jsapi.h"
 #include "xpcpublic.h"
 #include "prprf.h"
+#include "prenv.h"
 
 #include "nsIAppStartup.h"
 #include "nsIFile.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
@@ -43,10 +44,11 @@
 #ifdef MOZ_BACKGROUNDTASKS
 #  include "mozilla/BackgroundTasks.h"
 #endif
 #include "mozilla/CmdLineAndEnvUtils.h"
 #include "mozilla/Components.h"
+#include "mozilla/DebugOnly.h"
 #include "mozilla/Services.h"
 #include "mozilla/Omnijar.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ProfilerLabels.h"
 #include "mozilla/glean/ToolkitXreMetrics.h"
@@ -362,11 +364,13 @@
   }
 #if defined(XP_UNIX) || defined(XP_MACOSX)
   else if (!strcmp(aProperty, XRE_SYS_NATIVE_MANIFESTS)) {
     rv = ::GetSystemParentDirectory(getter_AddRefs(file));
   } else if (!strcmp(aProperty, XRE_USER_NATIVE_MANIFESTS)) {
-    rv = GetUserDataDirectoryHome(getter_AddRefs(file), false);
+    // Keep forcing the legacy path for compatibility
+    rv = GetUserDataDirectoryHome(getter_AddRefs(file), /* aLocal */ false,
+                                  /* aForceLegacy */ true);
     NS_ENSURE_SUCCESS(rv, rv);
 #  if defined(XP_MACOSX)
     rv = file->AppendNative("Mozilla"_ns);
 #  else   // defined(XP_MACOSX)
     rv = file->AppendNative(".mozilla"_ns);
@@ -915,11 +919,12 @@
   nsCOMPtr<nsIFile> appRootDirFile;
   nsCOMPtr<nsIFile> localDir;
   nsAutoString appDirPath;
   if (NS_FAILED(appFile->GetParent(getter_AddRefs(appRootDirFile))) ||
       NS_FAILED(appRootDirFile->GetPath(appDirPath)) ||
-      NS_FAILED(GetUserDataDirectoryHome(getter_AddRefs(localDir), true))) {
+      NS_FAILED(GetUserDataDirectoryHome(getter_AddRefs(localDir),
+                                         /* aLocal */ true))) {
     return NS_ERROR_FAILURE;
   }
 
   int32_t dotIndex = appDirPath.RFind(u".app");
   if (dotIndex == kNotFound) {
@@ -1052,11 +1057,12 @@
   return NS_OK;
 }
 
 // Return the home directory that will contain user data
 nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
-                                                    bool aLocal) {
+                                                    bool aLocal,
+                                                    bool aForceLegacy) {
   // Copied from nsAppFileLocationProvider (more or less)
   nsCOMPtr<nsIFile> localDir;
 
   if (aLocal && gDataDirHomeLocal) {
     return gDataDirHomeLocal->Clone(aFile);
@@ -1107,43 +1113,39 @@
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   MOZ_TRY(NS_NewLocalFile(path, getter_AddRefs(localDir)));
 #elif defined(XP_UNIX)
-  const char* homeDir = getenv("HOME");
+  const char* homeDir = PR_GetEnv("HOME");
   if (!homeDir || !*homeDir) return NS_ERROR_FAILURE;
 
 #  ifdef ANDROID /* We want (ProfD == ProfLD) on Android. */
-  aLocal = false;
-#  endif
-
+  MOZ_TRY(NS_NewNativeLocalFile(nsDependentCString(homeDir),
+                                getter_AddRefs(localDir)));
+#  else
   if (aLocal) {
-    // If $XDG_CACHE_HOME is defined use it, otherwise use $HOME/.cache.
-    const char* cacheHome = getenv("XDG_CACHE_HOME");
-    if (cacheHome && *cacheHome) {
-      MOZ_TRY(NS_NewNativeLocalFile(nsDependentCString(cacheHome),
-                                    getter_AddRefs(localDir)));
-    } else {
-      MOZ_TRY(NS_NewNativeLocalFile(nsDependentCString(homeDir),
-                                    getter_AddRefs(localDir)));
-      MOZ_TRY(localDir->AppendNative(".cache"_ns));
-    }
+    // Not forcing legacy because cache can be lost without consequences, so
+    // there is no real requirement to keep compatibility here
+    MOZ_TRY(nsXREDirProvider::GetLegacyOrXDGCachePath(
+        homeDir, getter_AddRefs(localDir)));
   } else {
-    MOZ_TRY(NS_NewNativeLocalFile(nsDependentCString(homeDir),
-                                  getter_AddRefs(localDir)));
+    MOZ_TRY(nsXREDirProvider::GetLegacyOrXDGHomePath(
+        homeDir, getter_AddRefs(localDir), aForceLegacy));
   }
+#  endif  // ANDROID
 #else
 #  error "Don't know how to get product dir on your platform"
 #endif
 
   localDir.forget(aFile);
   return NS_OK;
 }
 
 nsresult nsXREDirProvider::GetSysUserExtensionsDirectory(nsIFile** aFile) {
   nsCOMPtr<nsIFile> localDir;
-  nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), false);
+  nsresult rv = GetUserDataDirectoryHome(
+      getter_AddRefs(localDir), /* aLocal */ false, /* aForceLegacy */ true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = AppendSysUserExtensionPath(localDir);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1251,20 +1253,227 @@
 #  error "Don't know how to get XRE user extension path on your platform"
 #endif
   return NS_OK;
 }
 
+#if defined(MOZ_WIDGET_GTK)
+/*
+ * Return whether MOZ_LEGACY_HOME == 1, via environment or at build time
+ */
+bool nsXREDirProvider::IsForceLegacyHome() {
+#  if !defined(MOZ_LEGACY_HOME)
+  const char* legacyhomedir = PR_GetEnv("MOZ_LEGACY_HOME");
+  return legacyhomedir && legacyhomedir[0] == '1';
+#  else
+  return true;
+#  endif
+}
+
+/* static */
+nsresult nsXREDirProvider::AppendFromAppData(nsIFile* aFile, bool aIsDotted) {
+  // This might happen in xpcshell so assert that it is indeed in a xpcshell
+  // test. This assumes the xpcshell are ran through test harness.
+  if (!gAppData) {
+    mozilla::DebugOnly<const char*> xpcshell =
+        PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR");
+    MOZ_ASSERT(xpcshell, "gAppData can only be nullptr in xpcshell tests");
+    return NS_OK;
+  }
+
+  // Similar to nsXREDirProvider::AppendProfilePath.
+  // TODO: evaluate if refactoring might be required there in the future?
+  if (gAppData->profile) {
+    nsAutoCString profile;
+    profile = gAppData->profile;
+    MOZ_TRY(aFile->AppendRelativeNativePath(profile));
+  } else {
+    nsAutoCString vendor;
+    nsAutoCString appName;
+    vendor = gAppData->vendor;
+    appName = gAppData->name;
+    ToLowerCase(vendor);
+    ToLowerCase(appName);
+
+    MOZ_TRY(
+        aFile->AppendRelativeNativePath(aIsDotted ? ("."_ns + vendor) : vendor));
+    MOZ_TRY(aFile->AppendRelativeNativePath(appName));
+  }
+
+  return NS_OK;
+}
+
+/*
+ * Check if legacy directory exists, which can be:
+ *  (1) $HOME/.<gAppData->vendor>/<gAppData->appName>
+ *  (2) $HOME/<gAppData->profile>
+ *  (3) $HOME/<MOZ_USER_DIR>
+ *
+ * The MOZ_USER_DIR will also be defined in case (1), so first check the deeper
+ * directory.
+ */
+bool nsXREDirProvider::LegacyHomeExists(nsIFile** aFile) {
+  bool exists;
+  nsDependentCString homeDir(PR_GetEnv("HOME"));
+  nsCOMPtr<nsIFile> localDir;
+  nsCOMPtr<nsIFile> parentDir;
+
+  // check old config ~/.mozilla
+  nsresult rv = NS_NewNativeLocalFile(homeDir, getter_AddRefs(localDir));
+  NS_ENSURE_SUCCESS(rv, false);
+
+  rv = localDir->Clone(getter_AddRefs(parentDir));
+  NS_ENSURE_SUCCESS(rv, false);
+
+  // Handle (1) and (2)
+  rv = AppendFromAppData(localDir, true);
+  NS_ENSURE_SUCCESS(rv, false);
+
+  rv = localDir->Exists(&exists);
+  NS_ENSURE_SUCCESS(rv, false);
+
+  // Give a chance to (3)
+  if (!exists) {
+    nsCOMPtr<nsIFile> userDir;
+    rv = parentDir->Clone(getter_AddRefs(userDir));
+    NS_ENSURE_SUCCESS(rv, false);
+
+    nsAutoCString mozUserDir;
+    mozUserDir = nsLiteralCString(MOZ_USER_DIR);
+
+    rv = userDir->AppendRelativeNativePath(mozUserDir);
+    NS_ENSURE_SUCCESS(rv, false);
+
+    rv = userDir->Exists(&exists);
+    NS_ENSURE_SUCCESS(rv, false);
+  }
+
+  // If required, return the parent dir that may exist.
+  if (aFile) {
+    parentDir.forget(aFile);
+  }
+
+  return exists;
+}
+
+/* static */
+nsresult nsXREDirProvider::GetLegacyOrXDGEnvValue(const char* aHomeDir,
+                                                  const char* aEnvName,
+                                                  nsCString aSubdir,
+                                                  nsIFile** aFile) {
+  nsCOMPtr<nsIFile> localDir;
+  nsresult rv = NS_OK;
+
+  const char* envValue = PR_GetEnv(aEnvName);
+  if (envValue && *envValue) {
+    rv = NS_NewNativeLocalFile(nsDependentCString(envValue),
+                               getter_AddRefs(localDir));
+  }
+
+  // Explicitly check for rv failure because in case we get passed an env
+  // value that is an invalid dir by the XDG specification level, it should
+  // be ignored. Per
+  // https://specifications.freedesktop.org/basedir-spec/0.8/: 
+  // "If an implementation encounters a relative path in any of
+  // these variables it should consider the path invalid and ignore it."
+  if (NS_FAILED(rv) || !envValue || !*envValue) {
+    MOZ_TRY(NS_NewNativeLocalFile(nsDependentCString(aHomeDir),
+                                  getter_AddRefs(localDir)));
+    MOZ_TRY(localDir->AppendNative(aSubdir));
+  }
+
+  localDir.forget(aFile);
+  return NS_OK;
+}
+
+/* static */
+nsresult nsXREDirProvider::GetLegacyOrXDGCachePath(const char* aHomeDir,
+                                                   nsIFile** aFile) {
+  return GetLegacyOrXDGEnvValue(aHomeDir, "XDG_CACHE_HOME", ".cache"_ns, aFile);
+}
+
+/*
+ * Check if XDG_CONFIG_HOME is here and use it or default to ${aHomeDir}/.config
+ */
+/* static */
+nsresult nsXREDirProvider::GetLegacyOrXDGConfigHome(const char* aHomeDir,
+                                                    nsIFile** aFile) {
+  return GetLegacyOrXDGEnvValue(aHomeDir, "XDG_CONFIG_HOME", ".config"_ns,
+                                aFile);
+}
+
+// Attempt to construct the HOME path depending on XDG or legacy status.
+nsresult nsXREDirProvider::GetLegacyOrXDGHomePath(const char* aHomeDir,
+                                                  nsIFile** aFile,
+                                                  bool aForceLegacy) {
+  nsCOMPtr<nsIFile> parentDir;
+  nsDependentCString homeDir(aHomeDir);
+
+  bool exists = LegacyHomeExists(getter_AddRefs(parentDir));
+  if (exists || IsForceLegacyHome() || aForceLegacy) {
+    parentDir.forget(aFile);
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIFile> localDir;
+
+  // If the build was made with --with-user-appdir=.fooProfile it needs to be
+  // applied and considered as a legacy path.
+  nsAutoCString mozUserDir;
+  mozUserDir = nsLiteralCString(MOZ_USER_DIR);
+  if (mozUserDir.get()[0] == '.') {
+    MOZ_TRY(NS_NewNativeLocalFile(nsDependentCString(aHomeDir),
+                                  getter_AddRefs(localDir)));
+    MOZ_TRY(localDir->AppendRelativeNativePath(mozUserDir));
+  } else {
+    // This might happen in xpcshell so assert that it is indeed in a xpcshell
+    // test
+    if (!gAppData) {
+      mozilla::DebugOnly<const char*> xpcshell =
+          PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR");
+      MOZ_ASSERT(xpcshell, "gAppData can only be nullptr in xpcshell tests");
+      return NS_OK;
+    }
+
+    // If the build was made against a specific profile name, MOZ_APP_PROFILE=
+    // then make sure we respect this and dont move to XDG directory
+    if (gAppData->profile) {
+      MOZ_TRY(NS_NewNativeLocalFile(nsDependentCString(aHomeDir),
+                                    getter_AddRefs(localDir)));
+    } else {
+      MOZ_TRY(GetLegacyOrXDGConfigHome(aHomeDir, getter_AddRefs(localDir)));
+      MOZ_TRY(localDir->Clone(getter_AddRefs(parentDir)));
+    }
+
+    MOZ_TRY(AppendFromAppData(localDir, false));
+  }
+
+  // If required return the parent directory that matches the profile root
+  // directory.
+  if (aFile) {
+    parentDir.forget(aFile);
+  }
+
+  // The profile root directory needs to exists at that point.
+  MOZ_TRY(EnsureDirectoryExists(localDir));
+
+  return NS_OK;
+}
+#endif  // defined(MOZ_WIDGET_GTK)
+
 nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) {
   NS_ASSERTION(aFile, "Null pointer!");
 
   // If there is no XREAppData then there is no information to use to build
   // the profile path so just do nothing. This should only happen in xpcshell
   // tests.
   if (!gAppData) {
     return NS_OK;
   }
 
+  // Similar to nsXREDirProvider::AppendFromAppData.
+  // TODO: evaluate if refactoring might be required there in the future?
+
   nsAutoCString profile;
   nsAutoCString appName;
   nsAutoCString vendor;
   if (gAppData->profile) {
     profile = gAppData->profile;
@@ -1307,11 +1516,17 @@
   NS_ENSURE_SUCCESS(rv, rv);
 #elif defined(XP_UNIX)
   nsAutoCString folder;
   // Make it hidden (by starting with "."), except when local (the
   // profile is already under ~/.cache or XDG_CACHE_HOME).
-  if (!aLocal) folder.Assign('.');
+  if (!aLocal
+#  if defined(MOZ_WIDGET_GTK)
+      && (IsForceLegacyHome() || LegacyHomeExists(nullptr))
+#  endif
+  ) {
+    folder.Assign('.');
+  }
 
   if (!profile.IsEmpty()) {
     // Skip any leading path characters
     const char* profileStart = profile.get();
     while (*profileStart == '/' || *profileStart == '\\') profileStart++;
diff --git a/toolkit/xre/test/browser.toml b/toolkit/xre/test/browser.toml
--- a/toolkit/xre/test/browser.toml
+++ b/toolkit/xre/test/browser.toml
@@ -2,5 +2,8 @@
 tags = "os_integration"
 
 ["browser_checkdllblockliststate.js"]
 run-if = ["os == 'win'"]
 skip-if = ["ccov"] # Bug 1531789
+
+["browser_xdg_pref.js"]
+run-if = ["os == 'linux'"]
diff --git a/toolkit/xre/test/browser_xdg_pref.js b/toolkit/xre/test/browser_xdg_pref.js
new file mode 100644
--- /dev/null
+++ b/toolkit/xre/test/browser_xdg_pref.js
@@ -0,0 +1,11 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/publicdomain/zero/1.0/
+
+add_task(async function test_pref_is_true() {
+  Assert.equal(true, Services.prefs.getBoolPref("widget.support-xdg-config"));
+});
+
+add_task(async function test_pref_is_locked() {
+  Services.prefs.setBoolPref("widget.support-xdg-config", false);
+  Assert.equal(true, Services.prefs.getBoolPref("widget.support-xdg-config"));
+});
diff --git a/xpcom/io/moz.build b/xpcom/io/moz.build
--- a/xpcom/io/moz.build
+++ b/xpcom/io/moz.build
@@ -163,6 +163,7 @@
     DEFINES["HAVE_USR_LIB64_DIR"] = True
 
 LOCAL_INCLUDES += [
     "!..",
     "../build",
+    "/toolkit/xre",
 ]
diff --git a/xpcom/io/nsAppFileLocationProvider.cpp b/xpcom/io/nsAppFileLocationProvider.cpp
--- a/xpcom/io/nsAppFileLocationProvider.cpp
+++ b/xpcom/io/nsAppFileLocationProvider.cpp
@@ -11,10 +11,11 @@
 #include "nsAtom.h"
 #include "nsIDirectoryService.h"
 #include "nsIFile.h"
 #include "nsString.h"
 #include "nsSimpleEnumerator.h"
+#include "nsXREDirProvider.h"
 #include "prenv.h"
 #include "nsCRT.h"
 #if defined(MOZ_WIDGET_COCOA)
 #  include <Carbon/Carbon.h>
 #  include "CocoaFileUtils.h"
@@ -166,11 +167,12 @@
 
 //----------------------------------------------------------------------------------------
 // GetProductDirectory - Gets the directory which contains the application data
 // folder
 //
-// UNIX   : ~/.mozilla/
+// UNIX   : ~/.mozilla/ or ${XDG_CONFIG_HOME:-~/.config}/mozilla
+//          if env var MOZ_LEGACY_HOME is set to 1, then ~/.mozilla/ is used
 // WIN    : <Application Data folder on user's machine>\Mozilla
 // Mac    : :Documents:Mozilla:
 //----------------------------------------------------------------------------------------
 nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile,
                                                         bool aLocal) {
@@ -202,25 +204,53 @@
                              getter_AddRefs(localDir));
   if (NS_FAILED(rv)) {
     return rv;
   }
 #elif defined(XP_UNIX)
-  rv = NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")),
+  const char* homeDir = PR_GetEnv("HOME");
+  rv = NS_NewNativeLocalFile(nsDependentCString(homeDir),
                              getter_AddRefs(localDir));
   if (NS_FAILED(rv)) {
     return rv;
   }
+
+#  if defined(MOZ_WIDGET_GTK)
+  rv = nsXREDirProvider::GetLegacyOrXDGHomePath(homeDir,
+                                                getter_AddRefs(localDir));
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+#  endif
+
 #else
 #  error dont_know_how_to_get_product_dir_on_your_platform
 #endif
 
-  rv = localDir->AppendRelativeNativePath(DEFAULT_PRODUCT_DIR);
+#if defined(MOZ_WIDGET_GTK)
+  bool legacyExists = nsXREDirProvider::LegacyHomeExists(nullptr);
+  if (legacyExists || nsXREDirProvider::IsForceLegacyHome()) {
+    nsAutoCString productDir;
+    nsAutoCString mozUserDir;
+    mozUserDir = nsLiteralCString(MOZ_USER_DIR);
+    if (mozUserDir.get()[0] != '.') {
+      productDir = "."_ns + DEFAULT_PRODUCT_DIR;
+    } else {
+      productDir = DEFAULT_PRODUCT_DIR;
+    }
+    rv = localDir->AppendNative(productDir);
+  } else {
+    rv = localDir->AppendNative(DEFAULT_PRODUCT_DIR);
+  }
+#else
+  rv = localDir->AppendNative(DEFAULT_PRODUCT_DIR);
+#endif
+
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = localDir->Exists(&exists);
 
+  rv = localDir->Exists(&exists);
   if (NS_SUCCEEDED(rv) && !exists) {
     rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
   }
 
   if (NS_FAILED(rv)) {
@@ -234,11 +264,12 @@
 
 //----------------------------------------------------------------------------------------
 // GetDefaultUserProfileRoot - Gets the directory which contains each user
 // profile dir
 //
-// UNIX   : ~/.mozilla/
+// UNIX   : ~/.mozilla/ or ${XDG_CONFIG_HOME:-~/.config}/mozilla
+//          if env var MOZ_LEGACY_HOME is set to 1, then ~/.mozilla/ is used
 // WIN    : <Application Data folder on user's machine>\Mozilla\Profiles
 // Mac    : :Documents:Mozilla:Profiles:
 //----------------------------------------------------------------------------------------
 nsresult nsAppFileLocationProvider::GetDefaultUserProfileRoot(
     nsIFile** aLocalFile, bool aLocal) {

openSUSE Build Service is sponsored by