1{ pkgs, config, lib, ... }:
2
3with lib;
4
5let
6 cfg = config.programs.firefox;
7
8 nmh = cfg.nativeMessagingHosts;
9
10 policyFormat = pkgs.formats.json { };
11
12 organisationInfo = ''
13 When this option is in use, Firefox will inform you that "your browser
14 is managed by your organisation". That message appears because NixOS
15 installs what you have declared here such that it cannot be overridden
16 through the user interface. It does not mean that someone else has been
17 given control of your browser, unless of course they also control your
18 NixOS configuration.
19 '';
20in
21{
22 options.programs.firefox = {
23 enable = mkEnableOption (mdDoc "the Firefox web browser");
24
25 package = mkOption {
26 type = types.package;
27 default = pkgs.firefox;
28 description = mdDoc "Firefox package to use.";
29 defaultText = literalExpression "pkgs.firefox";
30 relatedPackages = [
31 "firefox"
32 "firefox-beta-bin"
33 "firefox-bin"
34 "firefox-devedition-bin"
35 "firefox-esr"
36 ];
37 };
38
39 policies = mkOption {
40 type = policyFormat.type;
41 default = { };
42 description = mdDoc ''
43 Group policies to install.
44
45 See [Mozilla's documentation](https://github.com/mozilla/policy-templates/blob/master/README.md)
46 for a list of available options.
47
48 This can be used to install extensions declaratively! Check out the
49 documentation of the `ExtensionSettings` policy for details.
50
51 ${organisationInfo}
52 '';
53 };
54
55 preferences = mkOption {
56 type = with types; attrsOf (oneOf [ bool int string ]);
57 default = { };
58 description = mdDoc ''
59 Preferences to set from `about:config`.
60
61 Some of these might be able to be configured more ergonomically
62 using policies.
63
64 ${organisationInfo}
65 '';
66 };
67
68 preferencesStatus = mkOption {
69 type = types.enum [ "default" "locked" "user" "clear" ];
70 default = "locked";
71 description = mdDoc ''
72 The status of `firefox.preferences`.
73
74 `status` can assume the following values:
75 - `"default"`: Preferences appear as default.
76 - `"locked"`: Preferences appear as default and can't be changed.
77 - `"user"`: Preferences appear as changed.
78 - `"clear"`: Value has no effect. Resets to factory defaults on each startup.
79 '';
80 };
81
82 languagePacks = mkOption {
83 # Available languages can be found in https://releases.mozilla.org/pub/firefox/releases/${cfg.package.version}/linux-x86_64/xpi/
84 type = types.listOf (types.enum ([
85 "ach"
86 "af"
87 "an"
88 "ar"
89 "ast"
90 "az"
91 "be"
92 "bg"
93 "bn"
94 "br"
95 "bs"
96 "ca-valencia"
97 "ca"
98 "cak"
99 "cs"
100 "cy"
101 "da"
102 "de"
103 "dsb"
104 "el"
105 "en-CA"
106 "en-GB"
107 "en-US"
108 "eo"
109 "es-AR"
110 "es-CL"
111 "es-ES"
112 "es-MX"
113 "et"
114 "eu"
115 "fa"
116 "ff"
117 "fi"
118 "fr"
119 "fy-NL"
120 "ga-IE"
121 "gd"
122 "gl"
123 "gn"
124 "gu-IN"
125 "he"
126 "hi-IN"
127 "hr"
128 "hsb"
129 "hu"
130 "hy-AM"
131 "ia"
132 "id"
133 "is"
134 "it"
135 "ja"
136 "ka"
137 "kab"
138 "kk"
139 "km"
140 "kn"
141 "ko"
142 "lij"
143 "lt"
144 "lv"
145 "mk"
146 "mr"
147 "ms"
148 "my"
149 "nb-NO"
150 "ne-NP"
151 "nl"
152 "nn-NO"
153 "oc"
154 "pa-IN"
155 "pl"
156 "pt-BR"
157 "pt-PT"
158 "rm"
159 "ro"
160 "ru"
161 "sco"
162 "si"
163 "sk"
164 "sl"
165 "son"
166 "sq"
167 "sr"
168 "sv-SE"
169 "szl"
170 "ta"
171 "te"
172 "th"
173 "tl"
174 "tr"
175 "trs"
176 "uk"
177 "ur"
178 "uz"
179 "vi"
180 "xh"
181 "zh-CN"
182 "zh-TW"
183 ]));
184 default = [ ];
185 description = mdDoc ''
186 The language packs to install.
187 '';
188 };
189
190 autoConfig = mkOption {
191 type = types.lines;
192 default = "";
193 description = mdDoc ''
194 AutoConfig files can be used to set and lock preferences that are not covered
195 by the policies.json for Mac and Linux. This method can be used to automatically
196 change user preferences or prevent the end user from modifiying specific
197 preferences by locking them. More info can be found in https://support.mozilla.org/en-US/kb/customizing-firefox-using-autoconfig.
198 '';
199 };
200
201 nativeMessagingHosts = mapAttrs (_: v: mkEnableOption (mdDoc v)) {
202 browserpass = "Browserpass support";
203 bukubrow = "Bukubrow support";
204 euwebid = "Web eID support";
205 ff2mpv = "ff2mpv support";
206 fxCast = "fx_cast support";
207 gsconnect = "GSConnect support";
208 jabref = "JabRef support";
209 passff = "PassFF support";
210 tridactyl = "Tridactyl support";
211 ugetIntegrator = "Uget Integrator support";
212 };
213 };
214
215 config = mkIf cfg.enable {
216 environment.systemPackages = [
217 (cfg.package.override {
218 extraPrefs = cfg.autoConfig;
219 extraNativeMessagingHosts = with pkgs; optionals nmh.ff2mpv [
220 ff2mpv
221 ] ++ optionals nmh.euwebid [
222 web-eid-app
223 ] ++ optionals nmh.gsconnect [
224 gnomeExtensions.gsconnect
225 ] ++ optionals nmh.jabref [
226 jabref
227 ] ++ optionals nmh.passff [
228 passff-host
229 ];
230 })
231 ];
232
233 nixpkgs.config.firefox = {
234 enableBrowserpass = nmh.browserpass;
235 enableBukubrow = nmh.bukubrow;
236 enableEUWebID = nmh.euwebid;
237 enableTridactylNative = nmh.tridactyl;
238 enableUgetIntegrator = nmh.ugetIntegrator;
239 enableFXCastBridge = nmh.fxCast;
240 };
241
242 environment.etc =
243 let
244 policiesJSON = policyFormat.generate "firefox-policies.json" { inherit (cfg) policies; };
245 in
246 mkIf (cfg.policies != { }) {
247 "firefox/policies/policies.json".source = "${policiesJSON}";
248 };
249
250 # Preferences are converted into a policy
251 programs.firefox.policies = {
252 Preferences = (mapAttrs
253 (_: value: { Value = value; Status = cfg.preferencesStatus; })
254 cfg.preferences);
255 ExtensionSettings = listToAttrs (map
256 (lang: nameValuePair
257 "langpack-${lang}@firefox.mozilla.org"
258 {
259 installation_mode = "normal_installed";
260 install_url = "https://releases.mozilla.org/pub/firefox/releases/${cfg.package.version}/linux-x86_64/xpi/${lang}.xpi";
261 }
262 )
263 cfg.languagePacks);
264 };
265 };
266
267 meta.maintainers = with maintainers; [ danth ];
268}