1
0
Fork 0
mirror of https://github.com/nix-community/home-manager synced 2024-12-05 01:19:46 +01:00
home-manager/modules/programs/firefox.nix
Damien Cassou 1710db409d
firefox: show how to get pre-packaged add-ons
PR #1296

(cherry picked from commit ca6fcc92a1)
2020-06-16 23:48:25 +02:00

309 lines
9.2 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.

{ config, lib, pkgs, ... }:
with lib;
let
inherit (pkgs.stdenv.hostPlatform) isDarwin;
cfg = config.programs.firefox;
mozillaConfigPath =
if isDarwin
then "Library/Application Support/Mozilla"
else ".mozilla";
firefoxConfigPath =
if isDarwin
then "Library/Application Support/Firefox"
else "${mozillaConfigPath}/firefox";
profilesPath =
if isDarwin
then "${firefoxConfigPath}/Profiles"
else firefoxConfigPath;
# The extensions path shared by all profiles; will not be supported
# by future Firefox versions.
extensionPath = "extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
extensionsEnvPkg = pkgs.buildEnv {
name = "hm-firefox-extensions";
paths = cfg.extensions;
};
profiles =
flip mapAttrs' cfg.profiles (_: profile:
nameValuePair "Profile${toString profile.id}" {
Name = profile.name;
Path =
if isDarwin
then "Profiles/${profile.path}"
else profile.path;
IsRelative = 1;
Default = if profile.isDefault then 1 else 0;
}
) // {
General = {
StartWithLastProfile = 1;
};
};
profilesIni = generators.toINI {} profiles;
mkUserJs = prefs: extraPrefs: ''
// Generated by Home Manager.
${concatStrings (mapAttrsToList (name: value: ''
user_pref("${name}", ${builtins.toJSON value});
'') prefs)}
${extraPrefs}
'';
in
{
meta.maintainers = [ maintainers.rycee ];
imports = [
(mkRemovedOptionModule ["programs" "firefox" "enableGoogleTalk"]
"Support for this option has been removed.")
(mkRemovedOptionModule ["programs" "firefox" "enableIcedTea"]
"Support for this option has been removed.")
];
options = {
programs.firefox = {
enable = mkEnableOption "Firefox";
package = mkOption {
type = types.package;
default =
if versionAtLeast config.home.stateVersion "19.09"
then pkgs.firefox
else pkgs.firefox-unwrapped;
defaultText = literalExample "pkgs.firefox";
description = ''
The Firefox package to use. If state version  19.09 then
this should be a wrapped Firefox package. For earlier state
versions it should be an unwrapped Firefox package.
'';
};
extensions = mkOption {
type = types.listOf types.package;
default = [];
example = literalExample ''
with pkgs.nur.repos.rycee.firefox-addons; [
https-everywhere
privacy-badger
]
'';
description = ''
List of Firefox add-on packages to install. Some
pre-packaged add-ons are accessible from NUR,
<link xlink:href="https://github.com/nix-community/NUR"/>.
Once you have NUR installed run
<screen language="console">
<prompt>$</prompt> <userinput>nix-env -f '&lt;nixpkgs&gt;' -qaP -A nur.repos.rycee.firefox-addons</userinput>
</screen>
to list the available Firefox add-ons.
</para><para>
Note that it is necessary to manually enable these
extensions inside Firefox after the first installation.
'';
};
profiles = mkOption {
type = types.attrsOf (types.submodule ({config, name, ...}: {
options = {
name = mkOption {
type = types.str;
default = name;
description = "Profile name.";
};
id = mkOption {
type = types.ints.unsigned;
default = 0;
description = ''
Profile ID. This should be set to a unique number per profile.
'';
};
settings = mkOption {
type = with types; attrsOf (either bool (either int str));
default = {};
example = literalExample ''
{
"browser.startup.homepage" = "https://nixos.org";
"browser.search.region" = "GB";
"browser.search.isUS" = false;
"distribution.searchplugins.defaultLocale" = "en-GB";
"general.useragent.locale" = "en-GB";
"browser.bookmarks.showMobileBookmarks" = true;
}
'';
description = "Attribute set of Firefox preferences.";
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Extra preferences to add to <filename>user.js</filename>.
'';
};
userChrome = mkOption {
type = types.lines;
default = "";
description = "Custom Firefox user chrome CSS.";
example = ''
/* Hide tab bar in FF Quantum */
@-moz-document url("chrome://browser/content/browser.xul") {
#TabsToolbar {
visibility: collapse !important;
margin-bottom: 21px !important;
}
#sidebar-box[sidebarcommand="treestyletab_piro_sakura_ne_jp-sidebar-action"] #sidebar-header {
visibility: collapse !important;
}
}
'';
};
userContent = mkOption {
type = types.lines;
default = "";
description = "Custom Firefox user content CSS.";
example = ''
/* Hide scrollbar in FF Quantum */
*{scrollbar-width:none !important}
'';
};
path = mkOption {
type = types.str;
default = name;
description = "Profile path.";
};
isDefault = mkOption {
type = types.bool;
default = config.id == 0;
defaultText = "true if profile ID is 0";
description = "Whether this is a default profile.";
};
};
}));
default = {};
description = "Attribute set of Firefox profiles.";
};
enableAdobeFlash = mkOption {
type = types.bool;
default = false;
description = "Whether to enable the unfree Adobe Flash plugin.";
};
};
};
config = mkIf cfg.enable {
assertions = [
(
let
defaults =
catAttrs "name" (filter (a: a.isDefault) (attrValues cfg.profiles));
in {
assertion = cfg.profiles == {} || length defaults == 1;
message =
"Must have exactly one default Firefox profile but found "
+ toString (length defaults)
+ optionalString (length defaults > 1)
(", namely " + concatStringsSep ", " defaults);
}
)
(
let
duplicates =
filterAttrs (_: v: length v != 1)
(zipAttrs
(mapAttrsToList (n: v: { "${toString v.id}" = n; })
(cfg.profiles)));
mkMsg = n: v: " - ID ${n} is used by ${concatStringsSep ", " v}";
in {
assertion = duplicates == {};
message =
"Must not have Firefox profiles with duplicate IDs but\n"
+ concatStringsSep "\n" (mapAttrsToList mkMsg duplicates);
}
)
];
home.packages =
let
# The configuration expected by the Firefox wrapper.
fcfg = {
enableAdobeFlash = cfg.enableAdobeFlash;
};
# A bit of hackery to force a config into the wrapper.
browserName = cfg.package.browserName
or (builtins.parseDrvName cfg.package.name).name;
# The configuration expected by the Firefox wrapper builder.
bcfg = setAttrByPath [browserName] fcfg;
package =
if isDarwin then
cfg.package
else if versionAtLeast config.home.stateVersion "19.09" then
cfg.package.override { cfg = fcfg; }
else
(pkgs.wrapFirefox.override { config = bcfg; }) cfg.package { };
in
[ package ];
home.file = mkMerge (
[{
"${mozillaConfigPath}/${extensionPath}" = mkIf (cfg.extensions != []) {
source = "${extensionsEnvPkg}/share/mozilla/${extensionPath}";
recursive = true;
};
"${firefoxConfigPath}/profiles.ini" = mkIf (cfg.profiles != {}) {
text = profilesIni;
};
}]
++ flip mapAttrsToList cfg.profiles (_: profile: {
"${profilesPath}/${profile.path}/chrome/userChrome.css" =
mkIf (profile.userChrome != "") {
text = profile.userChrome;
};
"${profilesPath}/${profile.path}/chrome/userContent.css" =
mkIf (profile.userContent != "") {
text = profile.userContent;
};
"${profilesPath}/${profile.path}/user.js" =
mkIf (profile.settings != {} || profile.extraConfig != "") {
text = mkUserJs profile.settings profile.extraConfig;
};
"${profilesPath}/${profile.path}/extensions" = mkIf (cfg.extensions != []) {
source = "${extensionsEnvPkg}/share/mozilla/${extensionPath}";
recursive = true;
force = true;
};
})
);
};
}