Added a module to configure browser based on the gecko engine, such as Firefox.

This module should provide similar functionality to the firefox module in
home-manager. Some notable differences between the two include:

* home-manager configures a single browser. This means that any configuration
  that cannot be done on a per-profile basis is shared between all
  profiles. This module configures a new copy of the browser for every profile,
  ensuring that *all* configuration can be on a per-profile basis.

  This might be seen as insanity in a regular distro, but in NixOS this is
  trivial to do and requires no extra storage space.

* home-manager modifies files in the user's directory to configure things such
  as extensions and search engines. This module avoids that when possible by
  pushing configuration into policies and preferences at a browser level.
  This is much nicer for impermanence-based systems.
This commit is contained in:
hylodon 2026-02-22 19:57:42 +00:00
parent 977595f7e8
commit 0f0c4c7727
10 changed files with 962 additions and 1 deletions

View file

@ -0,0 +1,210 @@
{
lib,
sLib,
info,
...
}:
let
submodule = isDefault: {
options = {
https-only = lib.mkOption {
type = lib.types.bool;
default = false; # if isDefault then false else config.default.https-only;
example = true;
description = "Whether ${
if isDefault then "all domains" else "this domain"
} should be accessed over https only.";
};
cookies = lib.mkOption {
type = lib.types.enum (
[
"forever"
"session"
"never"
true
false
]
++ lib.optional (!isDefault) null
);
default = if isDefault then "forever" else null;
example = "session";
description = ''
Determines how cookies are handled on this domain:
forever: Cookies are permitted
session: Cookies are permitted, but they are deleted when the session ends
never: Cookies are denied
true: Equivalent to "session"
false: Equivalent to "never"
${if isDefault then "" else "null: Use the default settings"}
'';
};
${if isDefault then null else "ubo"} = lib.mkOption {
type = lib.types.bool;
default = true;
example = false;
description = "Whether ublock-origin should be enabled on this domain.";
};
scripts = lib.mkOption {
type = (if isDefault then (x: x) else lib.types.nullOr) lib.types.bool;
default = if isDefault then true else null;
example = false;
description = "Whether to allow JavaScript to run on websites.${
if isDefault then "" else " If null, use the default settings."
}";
};
fonts = lib.mkOption {
type = (if isDefault then (x: x) else lib.types.nullOr) lib.types.bool;
default = if isDefault then true else null;
example = false;
description = "Whether to allow websites to use remote fonts.";
};
popups = lib.mkOption {
type = (if isDefault then (x: x) else lib.types.nullOr) lib.types.bool;
default = if isDefault then true else null;
example = false;
description = "Whether to allow popups.";
};
largeMedia = lib.mkOption {
type = (if isDefault then (x: x) else lib.types.nullOr) lib.types.bool;
default = if isDefault then true else null;
example = false;
description = "Whether to allow large media.";
};
subdomain = {
allow = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "google.com" ];
description = "List of subdomains that ${
if isDefault then "any" else "this"
} domain can load resources from.";
};
block = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "google.com" ];
description = "List of subdomains that ${
if isDefault then "any" else "this"
} domain cannot load resources from.";
};
noop = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "google.com" ];
description = "List of subdomains that ${
if isDefault then "any" else "this"
} domain can load resources from, if a static filter does not override this rule.";
};
};
${if isDefault then null else "filters"} = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "#irritating-popup" ];
description = "List of ublock filters to apply to this domain.";
};
};
};
in
{
options = {
per-site = {
default = lib.mkOption {
type = lib.types.submodule (submodule true);
default = { };
description = "Sets options for all websites.";
};
site = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule (submodule false));
default = { };
description = "Sets options on a per-website basis.";
};
};
};
preprocess =
{ per-site, ... }:
let
inherit (per-site) default site;
behavior =
if
builtins.elem default.cookies [
"forever"
"session"
true
]
then
"accept"
else
"reject";
filterCookies =
x:
builtins.concatLists
<| lib.mapAttrsToList (
k: v:
if builtins.elem v.cookies x then
[ "https://${k}/" ] ++ lib.optional (!v.https-only) "http://${k}/"
else
[ ]
)
<| site;
makeUboConf = domain: config: {
adminSettings = {
whitelist = lib.optional (!(config.ubo or true)) domain;
hostnameSwitchesString =
lib.optional (config.scripts != null) "no-scripting: ${domain} ${builtins.toJSON (!config.scripts)}"
++
lib.optional (config.fonts != null)
"no-remote-fonts: ${domain} ${builtins.toJSON (!config.fonts)}"
++ lib.optional (config.popups != null) "no-popups: ${domain} ${builtins.toJSON (!config.popups)}"
++
lib.optional (config.largeMedia != null)
"no-large-media: ${domain} ${builtins.toJSON (!config.largeMedia)}";
dynamicFilteringString =
builtins.map (x: "${domain} ${x} * allow") config.subdomain.allow
++ builtins.map (x: "${domain} ${x} * block") config.subdomain.block
++ builtins.map (x: "${domain} ${x} * noop") config.subdomain.noop;
userFilters = builtins.map (x: "${domain}##${x}") (config.filters or [ ]);
};
# toOverwrite = {
# trustedSiteDirectives = lib.optional (!(config.ubo or true)) domain;
# filters = builtins.map (x: "${domain}##${x}") (config.filters or []);
# };
};
in
{
policies = {
Cookies = {
Allow = filterCookies [ "forever" ];
AllowSession = filterCookies [
"session"
true
];
Block = filterCookies [
"never"
false
];
Behavior = behavior;
BehaviorPrivateBrowsing = behavior;
};
SanitizeOnShutdown.Cookies = builtins.elem default.cookies [
"session"
true
];
};
extensions.settings."uBlock0@raymondhill.net" =
sLib.recursiveMergeAll <| [ (makeUboConf "*" default) ] ++ lib.mapAttrsToList makeUboConf site;
};
}