diff --git a/extensions/pref/autoconfig/moz.build b/extensions/pref/autoconfig/moz.build index 0ef8aad2a969..a8292ea733d9 100644 --- a/extensions/pref/autoconfig/moz.build +++ b/extensions/pref/autoconfig/moz.build @@ -6,6 +6,6 @@ DIRS += ["src"] -XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.ini"] +XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.ini", "test/unit/xpcshell_snap.ini"] MARIONETTE_UNIT_MANIFESTS += ["test/marionette/manifest.ini"] diff --git a/extensions/pref/autoconfig/src/nsReadConfig.cpp b/extensions/pref/autoconfig/src/nsReadConfig.cpp index 39d1930add7d..06f54dd0ab77 100644 --- a/extensions/pref/autoconfig/src/nsReadConfig.cpp +++ b/extensions/pref/autoconfig/src/nsReadConfig.cpp @@ -26,6 +26,10 @@ #include "nspr.h" #include "nsXULAppAPI.h" +#if defined(MOZ_WIDGET_GTK) +# include "mozilla/WidgetUtilsGtk.h" +#endif // defined(MOZ_WIDGET_GTK) + using namespace mozilla; extern bool sandboxEnabled; @@ -243,7 +247,16 @@ nsresult nsReadConfig::openAndEvaluateJSFile(const char* aFileName, nsCOMPtr inStr; if (isBinDir) { nsCOMPtr jsFile; - rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(jsFile)); +#if defined(MOZ_WIDGET_GTK) + if (!mozilla::widget::IsRunningUnderFlatpakOrSnap()) { +#endif // defined(MOZ_WIDGET_GTK) + rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(jsFile)); +#if defined(MOZ_WIDGET_GTK) + } else { + rv = NS_GetSpecialDirectory(NS_OS_SYSTEM_CONFIG_DIR, + getter_AddRefs(jsFile)); + } +#endif // defined(MOZ_WIDGET_GTK) if (NS_FAILED(rv)) return rv; rv = jsFile->AppendNative(nsDependentCString(aFileName)); diff --git a/extensions/pref/autoconfig/test/unit/autoconfig-snap.cfg b/extensions/pref/autoconfig/test/unit/autoconfig-snap.cfg new file mode 100644 index 000000000000..c5c67bfbb7bb --- /dev/null +++ b/extensions/pref/autoconfig/test/unit/autoconfig-snap.cfg @@ -0,0 +1,4 @@ +// # don't remove this comment! (the first line is ignored by Mozilla) + +// Verify this one has a user value +pref("_autoconfig_.test.userpref-snap", "userpref-snap"); diff --git a/extensions/pref/autoconfig/test/unit/autoconfig_snap.js b/extensions/pref/autoconfig/test/unit/autoconfig_snap.js new file mode 100644 index 000000000000..bfa1df485955 --- /dev/null +++ b/extensions/pref/autoconfig/test/unit/autoconfig_snap.js @@ -0,0 +1,5 @@ +/* global pref */ +pref("general.config.sandbox_enabled", true); +pref("general.config.filename", "autoconfig-snap.cfg"); +pref("general.config.vendor", "autoconfig-snap"); +pref("general.config.obscure_value", 0); diff --git a/extensions/pref/autoconfig/test/unit/test_autoconfig_custom_path.js b/extensions/pref/autoconfig/test/unit/test_autoconfig_custom_path.js new file mode 100644 index 000000000000..bad16e39dba2 --- /dev/null +++ b/extensions/pref/autoconfig/test/unit/test_autoconfig_custom_path.js @@ -0,0 +1,23 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { updateAppInfo } = ChromeUtils.import( + "resource://testing-common/AppInfo.jsm" +); + +function run_test() { + let env = Cc["@mozilla.org/process/environment;1"].getService( + Ci.nsIEnvironment + ); + + let testDirName = do_get_cwd().clone(); + env.set("MOZ_SYSTEM_CONFIG_DIR", testDirName.path); + + updateAppInfo(); + + let customSysConfD = Services.dirsvc.get("SysConfD", Ci.nsIFile); + let parent = customSysConfD.parent; + let child = customSysConfD.leafName; + notEqual("/etc", parent.path, "SysConfD is not in /etc"); + equal("xpcshell", child, "SysConfD is xpcshell"); +} diff --git a/extensions/pref/autoconfig/test/unit/test_autoconfig_default_path.js b/extensions/pref/autoconfig/test/unit/test_autoconfig_default_path.js new file mode 100644 index 000000000000..54cf58847a78 --- /dev/null +++ b/extensions/pref/autoconfig/test/unit/test_autoconfig_default_path.js @@ -0,0 +1,13 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { updateAppInfo } = ChromeUtils.import( + "resource://testing-common/AppInfo.jsm" +); + +function run_test() { + updateAppInfo(); + + let defaultSysConfD = Services.dirsvc.get("SysConfD", Ci.nsIFile); + equal("/etc/xpcshell", defaultSysConfD.path, "SysConfD is in /etc"); +} diff --git a/extensions/pref/autoconfig/test/unit/test_autoconfig_snap.js b/extensions/pref/autoconfig/test/unit/test_autoconfig_snap.js new file mode 100644 index 000000000000..cd6003cf93e2 --- /dev/null +++ b/extensions/pref/autoconfig/test/unit/test_autoconfig_snap.js @@ -0,0 +1,80 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* eslint no-unsafe-finally: "off"*/ +/* Turning off this rule to allow control flow operations in finally block + * http://eslint.org/docs/rules/no-unsafe-finally */ + +const { updateAppInfo } = ChromeUtils.import( + "resource://testing-common/AppInfo.jsm" +); + +function ensureRemove(file) { + try { + file.remove(false); + } catch (e) { + if (e.result != Cr.NS_ERROR_FILE_NOT_FOUND) { + throw e; + } + } +} + +async function run_test() { + let env = Cc["@mozilla.org/process/environment;1"].getService( + Ci.nsIEnvironment + ); + let prefs = Services.prefs.getBranch(null); + + let testDir = do_get_cwd(); + let confDir = testDir.clone(); + confDir.append("MozSystemConfigDir"); + env.set("MOZ_SYSTEM_CONFIG_DIR", confDir.path); + env.set("SNAP_INSTANCE_NAME", "xpcshell"); + + updateAppInfo(); + + let sysConfD = Services.dirsvc.get("SysConfD", Ci.nsIFile); + + let defaultPrefDExtra = sysConfD.clone(); + defaultPrefDExtra.append("defaults"); + defaultPrefDExtra.append("pref"); + + await IOUtils.makeDirectory(defaultPrefDExtra.path); + + const kAutoConfigFile = defaultPrefDExtra.clone(); + kAutoConfigFile.append("autoconfig_snap.js"); + const kAutoConfigCfg = sysConfD.clone(); + kAutoConfigCfg.append("autoconfig-snap.cfg"); + + let autoConfigJS = testDir.clone(); + autoConfigJS.append(kAutoConfigFile.leafName); + + let autoConfigCfg = testDir.clone(); + autoConfigCfg.append(kAutoConfigCfg.leafName); + + try { + autoConfigJS.copyTo(kAutoConfigFile.parent, kAutoConfigFile.leafName); + autoConfigCfg.copyTo(kAutoConfigCfg.parent, kAutoConfigCfg.leafName); + + // Make sure nsReadConfig is initialized. + Cc["@mozilla.org/readconfig;1"].getService(Ci.nsISupports); + Services.prefs.resetPrefs(); + + Services.obs.notifyObservers( + Services.prefs, + "prefservice:before-read-userprefs" + ); + + ok(prefs.prefHasUserValue("_autoconfig_.test.userpref-snap")); + equal( + "userpref-snap", + prefs.getStringPref("_autoconfig_.test.userpref-snap") + ); + + Services.prefs.resetPrefs(); + } finally { + ensureRemove(kAutoConfigFile); + ensureRemove(kAutoConfigCfg); + Services.prefs.resetPrefs(); + } +} diff --git a/extensions/pref/autoconfig/test/unit/xpcshell.ini b/extensions/pref/autoconfig/test/unit/xpcshell.ini index cf9235ba8893..4db81966f47e 100644 --- a/extensions/pref/autoconfig/test/unit/xpcshell.ini +++ b/extensions/pref/autoconfig/test/unit/xpcshell.ini @@ -15,3 +15,7 @@ support-files = run-sequentially = very high failure rate in parallel [test_autoconfig_no_sandbox.js] run-sequentially = very high failure rate in parallel +[test_autoconfig_default_path.js] +run-if = os == 'linux' +[test_autoconfig_custom_path.js] +run-if = os == 'linux' diff --git a/extensions/pref/autoconfig/test/unit/xpcshell_snap.ini b/extensions/pref/autoconfig/test/unit/xpcshell_snap.ini new file mode 100644 index 000000000000..ff24d466460b --- /dev/null +++ b/extensions/pref/autoconfig/test/unit/xpcshell_snap.ini @@ -0,0 +1,8 @@ +[DEFAULT] +head = +skip-if = os != 'linux' + +[test_autoconfig_snap.js] +support-files = + autoconfig_snap.js + autoconfig-snap.cfg diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp index 338a54cc7c6f..f963bbbd74ab 100644 --- a/modules/libpref/Preferences.cpp +++ b/modules/libpref/Preferences.cpp @@ -107,6 +107,10 @@ # include "windows.h" #endif +#if defined(MOZ_WIDGET_GTK) +# include "mozilla/WidgetUtilsGtk.h" +#endif // defined(MOZ_WIDGET_GTK) + using namespace mozilla; using ipc::FileDescriptor; @@ -4860,6 +4864,23 @@ nsresult Preferences::InitInitialObjects(bool aIsStartup) { NS_WARNING("Error parsing application default preferences."); } +#if defined(MOZ_WIDGET_GTK) + // Under Flatpak/Snap package, load /etc/firefox/defaults/pref/*.js. + if (mozilla::widget::IsRunningUnderFlatpakOrSnap()) { + nsCOMPtr defaultSnapPrefDir; + rv = NS_GetSpecialDirectory(NS_OS_SYSTEM_CONFIG_DIR, + getter_AddRefs(defaultSnapPrefDir)); + NS_ENSURE_SUCCESS(rv, rv); + defaultSnapPrefDir->AppendNative("defaults"_ns); + defaultSnapPrefDir->AppendNative("pref"_ns); + + rv = pref_LoadPrefsInDir(defaultSnapPrefDir, nullptr, 0); + if (NS_FAILED(rv)) { + NS_WARNING("Error parsing application default preferences under Snap."); + } + } +#endif + // Load jar:$app/omni.jar!/defaults/preferences/*.js // or jar:$gre/omni.jar!/defaults/preferences/*.js. RefPtr appJarReader = Omnijar::GetReader(Omnijar::APP); diff --git a/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs b/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs index 015c4250b50b..b873f4a25693 100644 --- a/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs +++ b/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs @@ -532,12 +532,8 @@ class JSONPoliciesProvider { let configFile = null; if (AppConstants.platform == "linux" && AppConstants.MOZ_SYSTEM_POLICIES) { - let systemConfigFile = Cc["@mozilla.org/file/local;1"].createInstance( - Ci.nsIFile - ); - systemConfigFile.initWithPath( - "/etc/" + Services.appinfo.name.toLowerCase() + "/policies" - ); + let systemConfigFile = Services.dirsvc.get("SysConfD", Ci.nsIFile); + systemConfigFile.append("policies"); systemConfigFile.append(POLICIES_FILENAME); if (systemConfigFile.exists()) { return systemConfigFile; diff --git a/xpcom/ds/StaticAtoms.py b/xpcom/ds/StaticAtoms.py index 473135999fc7..59d706122bc5 100644 --- a/xpcom/ds/StaticAtoms.py +++ b/xpcom/ds/StaticAtoms.py @@ -2447,6 +2447,7 @@ STATIC_ATOMS = [ Atom("DirectoryService_OS_TemporaryDirectory", "TmpD"), Atom("DirectoryService_OS_CurrentProcessDirectory", "CurProcD"), Atom("DirectoryService_OS_CurrentWorkingDirectory", "CurWorkD"), + Atom("DirectoryService_OS_SystemConfigDir", "SysConfD"), # Atom("DirectoryService_OS_HomeDirectory", "Home"), # "Home" is present above Atom("DirectoryService_OS_DesktopDirectory", "Desk"), Atom("DirectoryService_InitCurrentProcess_dummy", "MozBinD"), diff --git a/xpcom/io/SpecialSystemDirectory.cpp b/xpcom/io/SpecialSystemDirectory.cpp index b5373510860b..117094a690d6 100644 --- a/xpcom/io/SpecialSystemDirectory.cpp +++ b/xpcom/io/SpecialSystemDirectory.cpp @@ -7,6 +7,7 @@ #include "SpecialSystemDirectory.h" #include "nsString.h" #include "nsDependentString.h" +#include "nsIXULAppInfo.h" #if defined(XP_WIN) @@ -185,6 +186,37 @@ static nsresult GetUnixHomeDir(nsIFile** aFile) { # endif } +static nsresult GetUnixSystemConfigDir(nsIFile** aFile) { +# if defined(ANDROID) + return NS_ERROR_FAILURE; +# else + nsCOMPtr appInfo = + do_GetService("@mozilla.org/xre/app-info;1"); + if (!appInfo) { + MOZ_CRASH("No appInfo"); + } + + nsAutoCString appName; + nsresult rv = appInfo->GetName(appName); + NS_ENSURE_SUCCESS(rv, rv); + + ToLowerCase(appName); + + const char* mozSystemConfigDir = PR_GetEnv("MOZ_SYSTEM_CONFIG_DIR"); + const char* defaultSystemConfigDir = "/etc"; + nsDependentCString sysConfigDir = nsDependentCString( + mozSystemConfigDir ? mozSystemConfigDir : defaultSystemConfigDir); + + rv = NS_NewNativeLocalFile(sysConfigDir, true, aFile); + NS_ENSURE_SUCCESS(rv, rv); + + (*aFile)->AppendNative(appName); + NS_ENSURE_SUCCESS(rv, rv); + + return rv; +# endif +} + /* The following license applies to the xdg_user_dir_lookup function: @@ -634,6 +666,9 @@ nsresult GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory, case Unix_XDG_Desktop: case Unix_XDG_Download: return GetUnixXDGUserDirectory(aSystemSystemDirectory, aFile); + + case Unix_SystemConfigDirectory: + return GetUnixSystemConfigDir(aFile); #endif default: diff --git a/xpcom/io/SpecialSystemDirectory.h b/xpcom/io/SpecialSystemDirectory.h index 167b80632cd1..8062c7549c55 100644 --- a/xpcom/io/SpecialSystemDirectory.h +++ b/xpcom/io/SpecialSystemDirectory.h @@ -50,7 +50,8 @@ enum SystemDirectories { Unix_HomeDirectory = 303, Unix_XDG_Desktop = 304, - Unix_XDG_Download = 306 + Unix_XDG_Download = 306, + Unix_SystemConfigDirectory = 307 }; nsresult GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory, diff --git a/xpcom/io/nsDirectoryService.cpp b/xpcom/io/nsDirectoryService.cpp index 679344ed35a7..9df030674917 100644 --- a/xpcom/io/nsDirectoryService.cpp +++ b/xpcom/io/nsDirectoryService.cpp @@ -442,6 +442,9 @@ nsDirectoryService::GetFile(const char* aProp, bool* aPersistent, rv = GetSpecialSystemDirectory(Unix_XDG_Download, getter_AddRefs(localFile)); *aPersistent = false; + } else if (inAtom == nsGkAtoms::DirectoryService_OS_SystemConfigDir) { + rv = GetSpecialSystemDirectory(Unix_SystemConfigDirectory, + getter_AddRefs(localFile)); } #endif diff --git a/xpcom/io/nsDirectoryServiceDefs.h b/xpcom/io/nsDirectoryServiceDefs.h index 8d0d2e20059f..c02b9c39e0a0 100644 --- a/xpcom/io/nsDirectoryServiceDefs.h +++ b/xpcom/io/nsDirectoryServiceDefs.h @@ -93,4 +93,8 @@ # define NS_UNIX_HOME_DIR NS_OS_HOME_DIR #endif +#if defined(MOZ_WIDGET_GTK) +# define NS_OS_SYSTEM_CONFIG_DIR "SysConfD" +#endif // defined(MOZ_WIDGET_GTK) + #endif