{ 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; }; }