2.home-manager/modules/programs/firefox/profiles/search.nix
Austin Horstman 0b44044694 treewide: meta.maintainers at top
Just make it consistent throughout codebase and easier to find
maintainers for a module.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-11-22 14:51:05 -06:00

552 lines
18 KiB
Nix
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
config,
lib,
pkgs,
appName,
package,
modulePath,
profilePath,
}:
let
inherit (lib)
mapAttrs
mapAttrs'
mkOption
optionalAttrs
types
warn
;
jsonFormat = pkgs.formats.json { };
# Map of nice field names to internal field names.
# This is intended to be exhaustive and should be
# updated at every version bump.
internalFieldNames =
(lib.genAttrs [
"name"
"isAppProvided"
"loadPath"
"updateInterval"
"updateURL"
"iconMapObj"
"metaData"
"orderHint"
"definedAliases"
"urls"
] (name: "_${name}"))
// {
searchForm = "__searchForm";
};
# Convenience to specify absolute path to icon
iconUrl = icon: if lib.isPath icon || lib.hasPrefix "/" icon then "file://${icon}" else icon;
processCustomEngineInput =
input:
{
name = input.id;
}
// (removeAttrs input [ "icon" ])
// optionalAttrs (input ? icon || input ? iconMapObj) {
iconMapObj = mapAttrs (name: iconUrl) (
(optionalAttrs (input ? icon) {
# Convenience to specify single icon instead of map
"16" = input.icon;
})
// (input.iconMapObj or { })
);
}
// {
# Required for custom engine configurations, loadPaths
# are unique identifiers that are generally formatted
# like: [source]/path/to/engine.xml
loadPath = "[home-manager]/${
lib.showAttrPath (
modulePath
++ [
"engines"
input.id
]
)
}";
};
processEngineInput =
id: input:
let
requiredInput = {
inherit id;
isAppProvided = input.isAppProvided or (removeAttrs input [ "metaData" ] == { });
metaData = input.metaData or { };
};
in
if requiredInput.isAppProvided then
requiredInput
else
lib.pipe (input // requiredInput) [
migrateEngineToV11
migrateEngineToV12
processCustomEngineInput
];
buildEngineConfig =
name: input:
mapAttrs' (name: value: {
name = internalFieldNames.${name} or name;
inherit value;
}) (processEngineInput name input);
sortEngineConfigs =
configs:
let
buildEngineConfigWithOrder =
order: id:
let
config =
configs.${id} or {
inherit id;
_isAppProvided = true;
_metaData = { };
};
in
config
// {
_metaData = config._metaData // {
inherit order;
};
};
engineConfigsWithoutOrder = lib.attrValues (removeAttrs configs config.order);
sortedEngineConfigs =
(lib.imap buildEngineConfigWithOrder config.order) ++ engineConfigsWithoutOrder;
in
sortedEngineConfigs;
engineInput =
config.engines
// {
# Infer config.default as an app provided
# engine if it's not in config.engines
${config.default} = config.engines.${config.default} or { };
}
// {
${config.privateDefault} = config.engines.${config.privateDefault} or { };
};
settings = {
version = 12;
engines = sortEngineConfigs (mapAttrs buildEngineConfig engineInput);
metaData =
optionalAttrs (config.default != null) {
defaultEngineId = config.default;
defaultEngineIdHash = "@hash@";
}
// optionalAttrs (config.privateDefault != null) {
privateDefaultEngineId = config.privateDefault;
privateDefaultEngineIdHash = "@privateHash@";
}
// {
useSavedOrder = config.order != [ ];
};
};
# Home Manager doesn't circumvent user consent and isn't acting
# maliciously. We're modifying the search outside of the browser, but
# a claim by Mozilla to remove this would be very anti-user, and
# is unlikely to be an issue for our use case.
disclaimer =
"By modifying this file, I agree that I am doing so "
+ "only within @appName@ itself, using official, user-driven search "
+ "engine selection processes, and in a way which does not circumvent "
+ "user consent. I acknowledge that any attempt to change this file "
+ "from outside of @appName@ is a malicious act, and will be responded "
+ "to accordingly.";
salt = if config.default != null then profilePath + config.default + disclaimer else null;
privateSalt =
if config.privateDefault != null then profilePath + config.privateDefault + disclaimer else null;
appNameVariable =
if package == null then
"appName=${lib.escapeShellArg appName}"
else
''
applicationIni="$(find ${lib.escapeShellArg package} -maxdepth 3 -path ${lib.escapeShellArg package}'/lib/*/application.ini' -print -quit)"
if test -n "$applicationIni"; then
appName="$(sed -n 's/^Name=\(.*\)$/\1/p' "$applicationIni" | head -n1)"
else
appName=${lib.escapeShellArg appName}
fi
'';
file =
pkgs.runCommand "search.json.mozlz4"
{
nativeBuildInputs = with pkgs; [
mozlz4a
openssl
];
json = builtins.toJSON settings;
inherit salt privateSalt;
}
''
${appNameVariable}
salt=''${salt//@appName@/"$appName"}
privateSalt=''${privateSalt//@appName@/"$appName"}
if [[ -n $salt ]]; then
export hash=$(echo -n "$salt" | openssl dgst -sha256 -binary | base64)
export privateHash=$(echo -n "$privateSalt" | openssl dgst -sha256 -binary | base64)
mozlz4a <(substituteStream json search.json.in --subst-var hash --subst-var privateHash) "$out"
else
mozlz4a <(echo "$json") "$out"
fi
'';
engineNameToId = {
# Derived from https://searchfox.org/mozilla-central/rev/e3f42ec9320748b2aab3d474d1e47075def9000c/services/settings/dumps/main/search-config-v2.json
"1&1 Suche" = "1und1";
"Allegro" = "allegro-pl";
"Amazon.co.jp" = "amazon-jp";
"Amazon.com" = "amazondotcom-us";
"Azerdict" = "azerdict";
"" = "baidu";
"Bing" = "bing";
"Ordbok" = "bok-NO";
"Ceneje.si" = "ceneji";
"Cc Cc" = "coccoc";
"" = "daum-kr";
"DuckDuckGo" = "ddg";
"eBay" = "ebay";
"Ecosia" = "ecosia";
"EUdict Eng->Cro" = "eudict";
"Am Faclair Beag" = "faclair-beag";
"GMX Suche" = "gmx-de";
"GMX Search" = "gmx-en-GB";
"GMX - Búsqueda web" = "gmx-es";
"GMX - Recherche web" = "gmx-fr";
"GMX Shopping" = "gmx-shopping";
"Google" = "google";
"Gule sider" = "gulesider-NO";
"LEO Eng-Deu" = "leo_ende_de";
" " = "longdo";
"mail.com search" = "mailcom";
"Mapy.cz" = "mapy-cz";
"MercadoLibre Argentina" = "mercadolibre-ar";
"MercadoLibre Chile" = "mercadolibre-cl";
"MercadoLibre Mexico" = "mercadolibre-mx";
"MercadoLivre" = "mercadolivre";
"" = "naver-kr";
"Odpiralni Časi" = "odpiralni";
"Pazaruvaj" = "pazaruvaj";
"Priberam" = "priberam";
"Prisjakt" = "prisjakt-sv-SE";
"Qwant" = "qwant";
"Qwant Junior" = "qwantjr";
"" = "rakuten";
"Readmoo " = "readmoo";
"Reddit" = "reddit";
"Salidzini.lv" = "salidzinilv";
"Seznam" = "seznam-cz";
"Tyda.se" = "tyda-sv-SE";
"Vatera.hu" = "vatera";
"WEB.DE Suche" = "webde";
"Wikipedia (en)" = "wikipedia";
"Wikipedia (nn)" = "wikipedia-NN";
"Wikipedia (nb)" = "wikipedia-NO";
"Wikipedia (af)" = "wikipedia-af";
"Biquipedia (an)" = "wikipedia-an";
"ويكيبيديا (ar)" = "wikipedia-ar";
"Wikipedia (ast)" = "wikipedia-ast";
"Vikipediya (az)" = "wikipedia-az";
"Вікіпедыя (be)" = "wikipedia-be";
"Вікіпэдыя (be-tarask)" = "wikipedia-be-tarask";
"Уикипедия (bg)" = "wikipedia-bg";
"িিি (bn)" = "wikipedia-bn";
"Wikipedia (br)" = "wikipedia-br";
"Wikipedia (bs)" = "wikipedia-bs";
"Viquipèdia (ca)" = "wikipedia-ca";
"Wicipedia (cy)" = "wikipedia-cy";
"Wikipedie (cs)" = "wikipedia-cz";
"Wikipedia (da)" = "wikipedia-da";
"Wikipedia (de)" = "wikipedia-de";
"Wikipedija (dsb)" = "wikipedia-dsb";
"Βικιπαίδεια (el)" = "wikipedia-el";
"Vikipedio (eo)" = "wikipedia-eo";
"Wikipedia (es)" = "wikipedia-es";
"Vikipeedia (et)" = "wikipedia-et";
"Wikipedia (eu)" = "wikipedia-eu";
"ویکیپدیا (fa)" = "wikipedia-fa";
"Wikipedia (fi)" = "wikipedia-fi";
"Wikipédia (fr)" = "wikipedia-fr";
"Wikipedy (fy)" = "wikipedia-fy-NL";
"Vicipéid (ga)" = "wikipedia-ga-IE";
"Uicipeid (gd)" = "wikipedia-gd";
"Wikipedia (gl)" = "wikipedia-gl";
"Vikipetã (gn)" = "wikipedia-gn";
"િિિ (gu)" = "wikipedia-gu";
"ויקיפדיה" = "wikipedia-he";
"ििि (hi)" = "wikipedia-hi";
"Wikipedija (hr)" = "wikipedia-hr";
"Wikipedija (hsb)" = "wikipedia-hsb";
"Wikipédia (hu)" = "wikipedia-hu";
"Վիքիպեդիա (hy)" = "wikipedia-hy";
"Wikipedia (ia)" = "wikipedia-ia";
"Wikipedia (id)" = "wikipedia-id";
"Wikipedia (is)" = "wikipedia-is";
"Wikipedia (it)" = "wikipedia-it";
"Wikipedia (ja)" = "wikipedia-ja";
" (ka)" = "wikipedia-ka";
"Wikipedia (kab)" = "wikipedia-kab";
"Уикипедия (kk)" = "wikipedia-kk";
" (km)" = "wikipedia-km";
"ಿಿಿ (kn)" = "wikipedia-kn";
" (ko)" = "wikipedia-kr";
"Wikipedia (lij)" = "wikipedia-lij";
" (lo)" = "wikipedia-lo";
"Vikipedija (lt)" = "wikipedia-lt";
"Vikipedeja (ltg)" = "wikipedia-ltg";
"Vikipēdija (lv)" = "wikipedia-lv";
"Википедија (mk)" = "wikipedia-mk";
"ििि (mr)" = "wikipedia-mr";
"Wikipedia (ms)" = "wikipedia-ms";
"က (my)" = "wikipedia-my";
"िििि (ne)" = "wikipedia-ne";
"Wikipedia (nl)" = "wikipedia-nl";
"Wikipèdia (oc)" = "wikipedia-oc";
"ਿ (pa)" = "wikipedia-pa";
"Wikipedia (pl)" = "wikipedia-pl";
"Wikipédia (pt)" = "wikipedia-pt";
"Wikipedia (rm)" = "wikipedia-rm";
"Wikipedia (ro)" = "wikipedia-ro";
"Википедия (ru)" = "wikipedia-ru";
" (si)" = "wikipedia-si";
"Wikipédia (sk)" = "wikipedia-sk";
"Wikipedija (sl)" = "wikipedia-sl";
"Wikipedia (sq)" = "wikipedia-sq";
"Википедија (sr)" = "wikipedia-sr";
"Wikipedia (sv)" = "wikipedia-sv-SE";
"ிிி (ta)" = "wikipedia-ta";
"ిి (te)" = "wikipedia-te";
"" = "wikipedia-th";
"Wikipedia (tl)" = "wikipedia-tl";
"Vikipedi (tr)" = "wikipedia-tr";
"Вікіпедія (uk)" = "wikipedia-uk";
"ویکیپیڈیا (ur)" = "wikipedia-ur";
"Vikipediya (uz)" = "wikipedia-uz";
"Wikipedia (vi)" = "wikipedia-vi";
"Wikipedia (wo)" = "wikipedia-wo";
"" = "wikipedia-zh-CN";
"Wikipedia (zh)" = "wikipedia-zh-TW";
"ಿಿ (kn)" = "wiktionary-kn";
"Wikiccionari (oc)" = "wiktionary-oc";
"ிி (ta)" = "wiktionary-ta";
"ి (te)" = "wiktionary-te";
"Wolne Lektury" = "wolnelektury-pl";
"Yahoo! JAPAN" = "yahoo-jp";
"Yahoo!" = "yahoo-jp-auctions";
"YouTube" = "youtube";
# Derived from https://searchfox.org/mozilla-central/rev/e3f42ec9320748b2aab3d474d1e47075def9000c/toolkit/components/search/SearchSettings.sys.mjs#32-44
"Wikipedia (hy)" = "wikipedia-hy";
"Wikipedia (kn)" = "wikipedia-kn";
"Vikipēdija" = "wikipedia-lv";
"Wikipedia (no)" = "wikipedia-NO";
"Wikipedia (el)" = "wikipedia-el";
"Wikipedia (lt)" = "wikipedia-lt";
"Wikipedia (my)" = "wikipedia-my";
"Wikipedia (pa)" = "wikipedia-pa";
"Wikipedia (pt)" = "wikipedia-pt";
"Wikipedia (si)" = "wikipedia-si";
"Wikipedia (tr)" = "wikipedia-tr";
};
migrateEngineNameToIdV7 =
engine:
if builtins.hasAttr engine engineNameToId then
warn
"Search engines are now referenced by id instead of by name, use '${engineNameToId.${engine}}' instead of '${engine}'"
engineNameToId.${engine}
else
engine;
migrateEngineToV11 =
engine:
engine
// lib.optionalAttrs (engine ? iconMapObj) {
iconMapObj = mapAttrs' (
name: value:
let
nameToIntResult = builtins.tryEval (lib.toInt name);
in
{
name =
if nameToIntResult.success then
name
else
let
size = toString (builtins.fromJSON name).width;
in
warn "JSON object names for 'iconMapObj' are deprecated, use '${size}' instead of '${name}'" size;
inherit value;
}
) engine.iconMapObj;
};
migrateEngineToV12 =
engine:
let
iconMapObj =
optionalAttrs (engine ? iconURL) {
"16" =
warn "'iconURL' is deprecated, use 'icon = ${lib.strings.escapeNixString engine.iconURL}' instead" engine.iconURL;
}
// optionalAttrs (engine ? iconUpdateURL) {
"16" =
warn "'iconUpdateURL' is deprecated, use 'icon = ${lib.strings.escapeNixString engine.iconUpdateURL}' instead" engine.iconUpdateURL;
}
// (engine.iconMapObj or { });
in
lib.throwIf (engine ? hasPreferredIcon) "hasPreferredIcon has been removed" (
removeAttrs engine [
"iconURL"
"iconUpdateURL"
]
)
// lib.optionalAttrs (iconMapObj != { }) { inherit iconMapObj; };
in
{
meta.maintainers = with lib.maintainers; [ kira-bruneau ];
imports = [ (pkgs.path + "/nixos/modules/misc/meta.nix") ];
options = {
enable = mkOption {
type = with types; bool;
default =
config.default != null
|| config.privateDefault != null
|| config.order != [ ]
|| config.engines != { };
internal = true;
};
force = mkOption {
type = with types; bool;
default = false;
description = ''
Whether to force replace the existing search
configuration. This is recommended since ${appName} will
replace the symlink for the search configuration on every
launch, but note that you'll lose any existing configuration
by enabling this.
'';
};
default = mkOption {
type = with types; nullOr str;
apply = engine: if engine != null then migrateEngineNameToIdV7 engine else null;
default = null;
example = "ddg";
description = ''
The default search engine used in the address bar and search
bar.
'';
};
privateDefault = mkOption {
type = with types; nullOr str;
apply = engine: if engine != null then migrateEngineNameToIdV7 engine else null;
default = null;
example = "ddg";
description = ''
The default search engine used in the Private Browsing.
'';
};
order = mkOption {
type = with types; uniq (listOf str);
apply = builtins.map migrateEngineNameToIdV7;
default = [ ];
example = [
"ddg"
"google"
];
description = ''
The order the search engines are listed in. Any engines that
aren't included in this list will be listed after these in an
unspecified order.
'';
};
engines = mkOption {
type = with types; attrsOf (attrsOf jsonFormat.type);
apply = mapAttrs' (
name: value: {
name = migrateEngineNameToIdV7 name;
inherit value;
}
);
default = { };
example = lib.literalExpression ''
{
nix-packages = {
name = "Nix Packages";
urls = [{
template = "https://search.nixos.org/packages";
params = [
{ name = "type"; value = "packages"; }
{ name = "query"; value = "{searchTerms}"; }
];
}];
icon = "''${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
definedAliases = [ "@np" ];
};
nixos-wiki = {
name = "NixOS Wiki";
urls = [{ template = "https://wiki.nixos.org/w/index.php?search={searchTerms}"; }];
iconMapObj."16" = "https://wiki.nixos.org/favicon.ico";
definedAliases = [ "@nw" ];
};
bing.metaData.hidden = true;
google.metaData.alias = "@g"; # builtin engines only support specifying one additional alias
}
'';
description = ''
Attribute set of search engine configurations. Engines that
only have {var}`metaData` specified will be treated as builtin
to ${appName}.
See [SearchEngine.jsm](https://searchfox.org/mozilla-central/rev/e3f42ec9320748b2aab3d474d1e47075def9000c/toolkit/components/search/SearchEngine.sys.mjs#890-923)
in ${appName}'s source for available options. We maintain a
mapping to let you specify all options in the referenced link
without underscores, but it may fall out of date with future
options.
Note, {var}`icon` is also a special option added by Home
Manager to make it convenient to specify absolute icon paths.
'';
};
file = mkOption {
type = with types; path;
default = file;
internal = true;
readOnly = true;
description = ''
Resulting search.json.mozlz4 file.
'';
};
};
}