176 lines
4.7 KiB
Nix
176 lines
4.7 KiB
Nix
|
|
{
|
||
|
|
lib,
|
||
|
|
pkgs,
|
||
|
|
sLib,
|
||
|
|
info,
|
||
|
|
geckoLib,
|
||
|
|
...
|
||
|
|
}@args:
|
||
|
|
|
||
|
|
let
|
||
|
|
# (a -> b -> c) -> [a] -> [b] -> [c]
|
||
|
|
mapProduct =
|
||
|
|
f: xs: ys:
|
||
|
|
builtins.concatMap (y: builtins.concatMap (x: f x y) xs) ys;
|
||
|
|
|
||
|
|
# (Lib -> Profile -> c) -> ProfileSettings -> [c]
|
||
|
|
mapLibAndProfile = f: x: mapProduct f allLibs <| builtins.attrValues <| x;
|
||
|
|
|
||
|
|
allLibs = builtins.attrValues <| lib.filterAttrs (k: _: k != "profiles") <| geckoLib;
|
||
|
|
allLibs' = allLibs ++ [ geckoLib.profiles ];
|
||
|
|
|
||
|
|
submodule =
|
||
|
|
{ config, name, ... }:
|
||
|
|
{
|
||
|
|
options = {
|
||
|
|
id = lib.mkOption {
|
||
|
|
type = lib.types.ints.unsigned;
|
||
|
|
default = 0;
|
||
|
|
description = "Profile ID";
|
||
|
|
};
|
||
|
|
|
||
|
|
name = lib.mkOption {
|
||
|
|
type = lib.types.str;
|
||
|
|
default = name;
|
||
|
|
description = "Profile name";
|
||
|
|
};
|
||
|
|
|
||
|
|
path = lib.mkOption {
|
||
|
|
type = lib.types.str;
|
||
|
|
default = name;
|
||
|
|
description = "Profile path";
|
||
|
|
};
|
||
|
|
|
||
|
|
isDefault = lib.mkOption {
|
||
|
|
type = lib.types.bool;
|
||
|
|
default = config.id == 0;
|
||
|
|
defaultText = "config.id == 0";
|
||
|
|
description = "Is profile the default?";
|
||
|
|
};
|
||
|
|
|
||
|
|
languagePacks = lib.mkOption {
|
||
|
|
type = lib.types.listOf lib.types.str;
|
||
|
|
default = [ ];
|
||
|
|
example = [
|
||
|
|
"en-GB"
|
||
|
|
"de"
|
||
|
|
];
|
||
|
|
description = "The language packs to install.";
|
||
|
|
};
|
||
|
|
}
|
||
|
|
// builtins.foldl' (x: y: x // y.options) { } allLibs;
|
||
|
|
};
|
||
|
|
|
||
|
|
writeProfilesIni = configPath: profileSettings: {
|
||
|
|
name = "${configPath}/profiles.ini";
|
||
|
|
value.text =
|
||
|
|
lib.generators.toINI { }
|
||
|
|
<|
|
||
|
|
lib.mapAttrs' (
|
||
|
|
_: v:
|
||
|
|
lib.nameValuePair "Profile${builtins.toString v.id}" {
|
||
|
|
Name = v.name;
|
||
|
|
Path = v.path;
|
||
|
|
IsRelative = 1;
|
||
|
|
Default = if v.isDefault then 1 else 0;
|
||
|
|
}
|
||
|
|
) profileSettings
|
||
|
|
// {
|
||
|
|
General = {
|
||
|
|
StartWithLastProfile = 1;
|
||
|
|
Version = 2;
|
||
|
|
};
|
||
|
|
};
|
||
|
|
};
|
||
|
|
in
|
||
|
|
{
|
||
|
|
options = lib.mkOption {
|
||
|
|
type = lib.types.attrsOf (lib.types.submodule submodule);
|
||
|
|
default = { };
|
||
|
|
description = "Sets browser settings on a per-profile basis.";
|
||
|
|
};
|
||
|
|
|
||
|
|
getDefaultProfileName =
|
||
|
|
profileSettings:
|
||
|
|
builtins.head
|
||
|
|
<| builtins.filter (x: profileSettings.${x}.isDefault)
|
||
|
|
<| builtins.attrNames
|
||
|
|
<| profileSettings;
|
||
|
|
|
||
|
|
process =
|
||
|
|
{ languagePacks, ... }:
|
||
|
|
let
|
||
|
|
extractVersion =
|
||
|
|
(x: if x == [ ] then info.base.version else builtins.head x)
|
||
|
|
<| builtins.match "([^-]*)-.*"
|
||
|
|
<| info.base.version;
|
||
|
|
in
|
||
|
|
{
|
||
|
|
policies.ExtensionSettings =
|
||
|
|
builtins.listToAttrs
|
||
|
|
<| builtins.map (lang: {
|
||
|
|
name = "langpack-${lang}@firefox.mozilla.org";
|
||
|
|
value = {
|
||
|
|
installation_mode = "force_installed";
|
||
|
|
install_url = "https://releases.mozilla.org/pub/firefox/releases/${extractVersion}/linux-x86_64/xpi/${lang}.xpi";
|
||
|
|
};
|
||
|
|
})
|
||
|
|
<| languagePacks;
|
||
|
|
};
|
||
|
|
|
||
|
|
assertions = profiles: [
|
||
|
|
{
|
||
|
|
assertion = profiles != { };
|
||
|
|
message = "No profiles are defined.";
|
||
|
|
}
|
||
|
|
{
|
||
|
|
assertion =
|
||
|
|
(x: x == 1)
|
||
|
|
<| builtins.length
|
||
|
|
<| builtins.filter (x: profiles.${x}.isDefault)
|
||
|
|
<| builtins.attrNames
|
||
|
|
<| profiles;
|
||
|
|
message = "One, and only one, profile must be marked as 'isDefault'. If you have not set this option on any profile, then one and only one profile must have id '0'.";
|
||
|
|
}
|
||
|
|
];
|
||
|
|
|
||
|
|
warnings = _: [ ];
|
||
|
|
|
||
|
|
evaluateAllProfiles =
|
||
|
|
profiles:
|
||
|
|
let
|
||
|
|
processLevel =
|
||
|
|
level: userConfig:
|
||
|
|
sLib.recursiveMergeAll
|
||
|
|
<| (x: [ userConfig ] ++ x)
|
||
|
|
<| builtins.map (myLib: (myLib.${level} or (_: { })) userConfig)
|
||
|
|
<| allLibs';
|
||
|
|
|
||
|
|
# Internal libraries can create their own configuration that needs to be merged
|
||
|
|
# into the user configuration (the user's takes priority). Generate that config.
|
||
|
|
finalConfig = builtins.mapAttrs (
|
||
|
|
_: v: processLevel "postprocess" <| processLevel "process" <| processLevel "preprocess" <| v
|
||
|
|
) profiles;
|
||
|
|
in
|
||
|
|
{
|
||
|
|
assertions =
|
||
|
|
mapLibAndProfile (x: x.assertions or (_: [ ])) finalConfig
|
||
|
|
++ geckoLib.profiles.assertions finalConfig;
|
||
|
|
|
||
|
|
warnings =
|
||
|
|
mapLibAndProfile (x: x.warnings or (_: [ ])) finalConfig ++ geckoLib.profiles.warnings finalConfig;
|
||
|
|
|
||
|
|
profiles = lib.mapAttrs (_: v: {
|
||
|
|
policies = v.policies;
|
||
|
|
prefs = v.prefs;
|
||
|
|
files = builtins.concatMap (x: (x.files or (_: [ ])) v) allLibs';
|
||
|
|
extFiles = builtins.concatMap (x: (x.extFiles or (_: [ ])) v) allLibs';
|
||
|
|
}) finalConfig;
|
||
|
|
|
||
|
|
files = [
|
||
|
|
(writeProfilesIni info.configPath finalConfig)
|
||
|
|
]
|
||
|
|
++ mapLibAndProfile (x: x.files or (_: [ ])) finalConfig;
|
||
|
|
};
|
||
|
|
}
|