Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions modules/programs/firefox.nix
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ let
mkFirefoxModule = import ./firefox/mkFirefoxModule.nix;

in {
meta.maintainers =
[ maintainers.rycee maintainers.kira-bruneau hm.maintainers.bricked ];
meta.maintainers = [ maintainers.rycee hm.maintainers.bricked ];

imports = [
(mkFirefoxModule {
Expand Down
250 changes: 16 additions & 234 deletions modules/programs/firefox/mkFirefoxModule.nix
Original file line number Diff line number Diff line change
Expand Up @@ -547,93 +547,17 @@ in {
description = "Whether this is a default profile.";
};

search = {
force = mkOption {
type = with types; bool;
default = false;
description = ''
Whether to force replace the existing search
configuration. This is recommended since ${name} 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;
default = null;
example = "DuckDuckGo";
description = ''
The default search engine used in the address bar and search bar.
'';
};

privateDefault = mkOption {
type = with types; nullOr str;
default = null;
example = "DuckDuckGo";
description = ''
The default search engine used in the Private Browsing.
'';
};

order = mkOption {
type = with types; uniq (listOf str);
default = [ ];
example = [ "DuckDuckGo" "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);
default = { };
example = literalExpression ''
{
"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" = {
urls = [{ template = "https://wiki.nixos.org/index.php?search={searchTerms}"; }];
iconUpdateURL = "https://wiki.nixos.org/favicon.png";
updateInterval = 24 * 60 * 60 * 1000; # every day
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 ${name}.

See [SearchEngine.jsm](https://searchfox.org/mozilla-central/rev/669329e284f8e8e2bb28090617192ca9b4ef3380/toolkit/components/search/SearchEngine.jsm#1138-1177)
in Firefox'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.
'';
};
search = mkOption {
type = types.submodule (args:
import ./profiles/search.nix {
inherit (args) config;
inherit lib pkgs;
appName = cfg.name;
modulePath = modulePath ++ [ "profiles" name "search" ];
profilePath = config.path;
});
default = { };
description = "Declarative search engine configuration.";
};

containersForce = mkOption {
Expand Down Expand Up @@ -853,152 +777,11 @@ in {
force = profile.containersForce;
};

"${profilesPath}/${profile.path}/search.json.mozlz4" = mkIf
(profile.search.default != null || profile.search.privateDefault != null
|| profile.search.order != [ ] || profile.search.engines != { }) {
force = profile.search.force;
source = let
settings = {
version = 6;
engines = let
# Map of nice field names to internal field names.
# This is intended to be exhaustive and should be
# updated at every version bump.
internalFieldNames = (genAttrs [
"name"
"isAppProvided"
"loadPath"
"hasPreferredIcon"
"updateInterval"
"updateURL"
"iconUpdateURL"
"iconURL"
"iconMapObj"
"metaData"
"orderHint"
"definedAliases"
"urls"
] (name: "_${name}")) // {
searchForm = "__searchForm";
};

processCustomEngineInput = input:
(removeAttrs input [ "icon" ])
// optionalAttrs (input ? icon) {
# Convenience to specify absolute path to icon
iconURL = "file://${input.icon}";
} // (optionalAttrs (input ? iconUpdateURL) {
# Convenience to default iconURL to iconUpdateURL so
# the icon is immediately downloaded from the URL
iconURL = input.iconURL or input.iconUpdateURL;
} // {
# Required for custom engine configurations, loadPaths
# are unique identifiers that are generally formatted
# like: [source]/path/to/engine.xml
loadPath = ''
[home-manager]/${moduleName}.profiles.${profile.name}.search.engines."${
replaceStrings [ "\\" ] [ "\\\\" ] input.name
}"'';
});

processEngineInput = name: input:
let
requiredInput = {
inherit name;
isAppProvided = input.isAppProvided or removeAttrs input
[ "metaData" ] == { };
metaData = input.metaData or { };
};
in if requiredInput.isAppProvided then
requiredInput
else
processCustomEngineInput (input // requiredInput);

buildEngineConfig = name: input:
mapAttrs' (name: value: {
name = internalFieldNames.${name} or name;
inherit value;
}) (processEngineInput name input);

sortEngineConfigs = configs:
let
buildEngineConfigWithOrder = order: name:
let
config = configs.${name} or {
_name = name;
_isAppProvided = true;
_metaData = { };
};
in config // {
_metaData = config._metaData // { inherit order; };
};

engineConfigsWithoutOrder =
attrValues (removeAttrs configs profile.search.order);

sortedEngineConfigs =
(imap buildEngineConfigWithOrder profile.search.order)
++ engineConfigsWithoutOrder;
in sortedEngineConfigs;

engineInput = profile.search.engines // {
# Infer profile.search.default as an app provided
# engine if it's not in profile.search.engines
${profile.search.default} =
profile.search.engines.${profile.search.default} or { };
} // {
${profile.search.privateDefault} =
profile.search.engines.${profile.search.privateDefault} or { };
};
in sortEngineConfigs (mapAttrs buildEngineConfig engineInput);

metaData = optionalAttrs (profile.search.default != null) {
current = profile.search.default;
hash = "@hash@";
} // optionalAttrs (profile.search.privateDefault != null) {
private = profile.search.privateDefault;
privateHash = "@privateHash@";
} // {
useSavedOrder = profile.search.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 = appName:
"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 profile.search.default != null then
profile.path + profile.search.default + disclaimer cfg.name
else
null;

privateSalt = if profile.search.privateDefault != null then
profile.path + profile.search.privateDefault
+ disclaimer cfg.name
else
null;
in pkgs.runCommand "search.json.mozlz4" {
nativeBuildInputs = with pkgs; [ mozlz4a openssl ];
json = builtins.toJSON settings;
inherit salt privateSalt;
} ''
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
'';
};
"${profilesPath}/${profile.path}/search.json.mozlz4" = {
enable = profile.search.enable;
force = profile.search.force;
source = profile.search.file;
};

"${profilesPath}/${profile.path}/extensions" =
mkIf (profile.extensions != [ ]) {
Expand All @@ -1025,4 +808,3 @@ in {
};
});
}

Loading