From 7e81c581a51e8e4aa30002332385034437655860 Mon Sep 17 00:00:00 2001 From: Ihar Hrachyshka Date: Sat, 15 Feb 2025 20:36:30 -0500 Subject: [PATCH] thunderbird, firefox: fix file conflict for native messaging hosts On Linux, both Thunderbird and Firefox use the same directory to contain native messaging host modules. On this platform, we have to merge both directories with native hosts into one. The patch introduces a separate helper module to manage native host directory generation. Now program modules (firefox, thunderbird) declare native hosts to initialize; while the new helper module determines *where* and *how* to merge them on disc. Signed-off-by: Ihar Hrachyshka --- modules/misc/mozilla-messaging-hosts.nix | 89 +++++++++++++++++++ modules/modules.nix | 1 + modules/programs/firefox/mkFirefoxModule.nix | 29 ++---- modules/programs/thunderbird.nix | 47 ++-------- .../programs/thunderbird/thunderbird.nix | 8 +- 5 files changed, 108 insertions(+), 66 deletions(-) create mode 100644 modules/misc/mozilla-messaging-hosts.nix diff --git a/modules/misc/mozilla-messaging-hosts.nix b/modules/misc/mozilla-messaging-hosts.nix new file mode 100644 index 00000000..45d1ce4b --- /dev/null +++ b/modules/misc/mozilla-messaging-hosts.nix @@ -0,0 +1,89 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + inherit (pkgs.stdenv) isDarwin; + + cfg = config.mozilla; + + defaultPaths = [ + # Link a .keep file to keep the directory around + (pkgs.writeTextDir "lib/mozilla/native-messaging-hosts/.keep" "") + ]; + + thunderbirdNativeMessagingHostsPath = if isDarwin then + "Library/Mozilla/NativeMessagingHosts" + else + ".mozilla/native-messaging-hosts"; + + firefoxNativeMessagingHostsPath = if isDarwin then + "Library/Application Support/Mozilla/NativeMessagingHosts" + else + ".mozilla/native-messaging-hosts"; +in { + meta.maintainers = + [ maintainers.booxter maintainers.rycee hm.maintainers.bricked ]; + + options.mozilla = { + firefoxNativeMessagingHosts = mkOption { + internal = true; + type = with types; listOf package; + default = [ ]; + description = '' + List of Firefox native messaging hosts to configure. + ''; + }; + + thunderbirdNativeMessagingHosts = mkOption { + internal = true; + type = with types; listOf package; + default = [ ]; + description = '' + List of Thunderbird native messaging hosts to configure. + ''; + }; + }; + + config = mkIf (cfg.firefoxNativeMessagingHosts != [ ] + || cfg.thunderbirdNativeMessagingHosts != [ ]) { + home.file = if isDarwin then + let + firefoxNativeMessagingHostsJoined = pkgs.symlinkJoin { + name = "ff-native-messaging-hosts"; + paths = defaultPaths ++ cfg.firefoxNativeMessagingHosts; + }; + thunderbirdNativeMessagingHostsJoined = pkgs.symlinkJoin { + name = "th-native-messaging-hosts"; + paths = defaultPaths ++ cfg.thunderbirdNativeMessagingHosts; + }; + in { + "${thunderbirdNativeMessagingHostsPath}" = { + source = + "${thunderbirdNativeMessagingHostsJoined}/lib/mozilla/native-messaging-hosts"; + recursive = true; + }; + + "${firefoxNativeMessagingHostsPath}" = { + source = + "${firefoxNativeMessagingHostsJoined}/lib/mozilla/native-messaging-hosts"; + recursive = true; + }; + } + else + let + nativeMessagingHostsJoined = pkgs.symlinkJoin { + name = "mozilla-native-messaging-hosts"; + # on Linux, the directory is shared between Firefox and Thunderbird; merge both into one + paths = defaultPaths ++ cfg.firefoxNativeMessagingHosts + ++ cfg.thunderbirdNativeMessagingHosts; + }; + in { + "${firefoxNativeMessagingHostsPath}" = { + source = + "${nativeMessagingHostsJoined}/lib/mozilla/native-messaging-hosts"; + recursive = true; + }; + }; + }; +} diff --git a/modules/modules.nix b/modules/modules.nix index 70a48b85..e42be971 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -30,6 +30,7 @@ let ./misc/fontconfig.nix ./misc/gtk.nix ./misc/lib.nix + ./misc/mozilla-messaging-hosts.nix ./misc/news.nix ./misc/nixgl.nix ./misc/numlock.nix diff --git a/modules/programs/firefox/mkFirefoxModule.nix b/modules/programs/firefox/mkFirefoxModule.nix index db787124..a36db370 100644 --- a/modules/programs/firefox/mkFirefoxModule.nix +++ b/modules/programs/firefox/mkFirefoxModule.nix @@ -30,23 +30,6 @@ let profilesPath = if isDarwin then "${cfg.configPath}/Profiles" else cfg.configPath; - nativeMessagingHostsPath = if isDarwin then - "${cfg.vendorPath}/NativeMessagingHosts" - else - "${cfg.vendorPath}/native-messaging-hosts"; - - nativeMessagingHostsJoined = pkgs.symlinkJoin { - name = "ff_native-messaging-hosts"; - paths = [ - # Link a .keep file to keep the directory around - (pkgs.writeTextDir "lib/mozilla/native-messaging-hosts/.keep" "") - # Link package configured native messaging hosts (entire browser actually) - cfg.finalPackage - ] - # Link user configured native messaging hosts - ++ cfg.nativeMessagingHosts; - }; - # The extensions path shared by all profiles; will not be supported # by future browser versions. extensionPath = "extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"; @@ -864,16 +847,14 @@ in { home.packages = lib.optional (cfg.finalPackage != null) cfg.finalPackage; + mozilla.firefoxNativeMessagingHosts = [ + cfg.finalPackage # package configured native messaging hosts (entire browser actually) + ] ++ cfg.nativeMessagingHosts; # user configured native messaging hosts + home.file = mkMerge ([{ "${cfg.configPath}/profiles.ini" = mkIf (cfg.profiles != { }) { text = profilesIni; }; - }] ++ optional (cfg.vendorPath != null) { - "${nativeMessagingHostsPath}" = { - source = - "${nativeMessagingHostsJoined}/lib/mozilla/native-messaging-hosts"; - recursive = true; - }; - } ++ flip mapAttrsToList cfg.profiles (_: profile: + }] ++ flip mapAttrsToList cfg.profiles (_: profile: # Merge the regular profile settings with extension settings mkMerge ([{ "${profilesPath}/${profile.path}/.keep".text = ""; diff --git a/modules/programs/thunderbird.nix b/modules/programs/thunderbird.nix index 339bcb59..a61209fa 100644 --- a/modules/programs/thunderbird.nix +++ b/modules/programs/thunderbird.nix @@ -136,24 +136,6 @@ let '') prefs)} ${extraPrefs} ''; - - nativeMessagingHostsPath = if isDarwin then - "${cfg.vendorPath}/NativeMessagingHosts" - else - "${cfg.vendorPath}/native-messaging-hosts"; - - nativeMessagingHostsJoined = pkgs.symlinkJoin { - name = "th_native-messaging-hosts"; - paths = [ - # Link a .keep file to keep the directory around - (pkgs.writeTextDir "lib/mozilla/native-messaging-hosts/.keep" "") - # Link package configured native messaging hosts (entire mail app actually) - cfg.package - ] - # Link user configured native messaging hosts - ++ cfg.nativeMessagingHosts; - }; - in { meta.maintainers = with hm.maintainers; [ d-dervishi jkarlson ]; @@ -176,20 +158,7 @@ in { description = "profile version, set null for nix-darwin"; }; - vendorPath = mkOption { - internal = true; - type = with types; nullOr str; - # Thunderbird doesn't look in `Application Support` on macOS for user - # config (in contrast to global settings that are the same for Firefox - # and Thunderbird): - # https://developer.thunderbird.net/add-ons/mailextensions/supported-webextension-api - default = if isDarwin then "Library/Mozilla" else ".mozilla"; - example = ".mozilla"; - description = - "Directory containing the native messaging hosts directory."; - }; - - nativeMessagingHosts = optionalAttrs (cfg.vendorPath != null) (mkOption { + nativeMessagingHosts = mkOption { visible = true; type = types.listOf types.package; default = [ ]; @@ -197,7 +166,7 @@ in { Additional packages containing native messaging hosts that should be made available to Thunderbird extensions. ''; - }); + }; profiles = mkOption { type = with types; @@ -441,16 +410,14 @@ in { ++ optional (any (p: p.withExternalGnupg) (attrValues cfg.profiles)) pkgs.gpgme; + mozilla.thunderbirdNativeMessagingHosts = [ + cfg.package # package configured native messaging hosts (entire mail app actually) + ] ++ cfg.nativeMessagingHosts; # user configured native messaging hosts + home.file = mkMerge ([{ "${thunderbirdConfigPath}/profiles.ini" = mkIf (cfg.profiles != { }) { text = generators.toINI { } profilesIni; }; - }] ++ optional (cfg.vendorPath != null) { - "${nativeMessagingHostsPath}" = { - source = - "${nativeMessagingHostsJoined}/lib/mozilla/native-messaging-hosts"; - recursive = true; - }; - } ++ flip mapAttrsToList cfg.profiles (name: profile: { + }] ++ flip mapAttrsToList cfg.profiles (name: profile: { "${thunderbirdProfilesPath}/${name}/chrome/userChrome.css" = mkIf (profile.userChrome != "") { text = profile.userChrome; }; diff --git a/tests/modules/programs/thunderbird/thunderbird.nix b/tests/modules/programs/thunderbird/thunderbird.nix index a4d095e3..555ea35d 100644 --- a/tests/modules/programs/thunderbird/thunderbird.nix +++ b/tests/modules/programs/thunderbird/thunderbird.nix @@ -37,14 +37,18 @@ }; }; + # Confirm that both Firefox and Thunderbird can be configured at the same time. + programs.firefox = { enable = true; }; + programs.thunderbird = { enable = true; # Disable warning so that platforms' behavior is the same darwinSetupWarning = false; - # Darwin doesn't support wrapped Thunderbird, using unwrapped instead - package = realPkgs.thunderbird-unwrapped; + # Darwin doesn't support wrapped Thunderbird, using unwrapped instead; + # using -latest- because ESR is currently broken on Darwin + package = realPkgs.thunderbird-latest-unwrapped; profiles = { first = {