diff --git a/hosts/common/programs/firefox/addons.nix b/hosts/common/programs/firefox/addons.nix index 2c61b37ae..21f19a989 100644 --- a/hosts/common/programs/firefox/addons.nix +++ b/hosts/common/programs/firefox/addons.nix @@ -45,7 +45,7 @@ in enable = lib.mkDefault false; #< obsoleted by uBlock Origin annoyances/cookies lists }; kagi-search = { - enable = lib.mkDefault false; + enable = lib.mkDefault true; }; # open-in-mpv = { # # test: `open-in-mpv 'mpv:///open?url=https://www.youtube.com/watch?v=dQw4w9WgXcQ'` diff --git a/hosts/common/programs/firefox/default.nix b/hosts/common/programs/firefox/default.nix index 37d2fc73f..7c896f810 100644 --- a/hosts/common/programs/firefox/default.nix +++ b/hosts/common/programs/firefox/default.nix @@ -270,24 +270,37 @@ in env.BROWSER = "firefox"; # used by misc tools like xdg-email, as fallback - fs = { - ".mozilla/firefox/bookmarks.html".symlink.target = ./bookmarks.html; + fs.".mozilla/firefox/bookmarks.html".symlink.target = ./bookmarks.html; + # instruct Firefox to put the profile in a predictable directory (so we can do things like persist just it). + # XXX: the directory *must* exist, even if empty; Firefox will not create the directory itself. + fs.".mozilla/firefox/profiles.ini".symlink.text = '' + [Profile0] + Name=default + IsRelative=1 + Path=default + Default=1 - # instruct Firefox to put the profile in a predictable directory (so we can do things like persist just it). - # XXX: the directory *must* exist, even if empty; Firefox will not create the directory itself. - ".mozilla/firefox/profiles.ini".symlink.text = '' - [Profile0] - Name=default - IsRelative=1 - Path=default - Default=1 + [General] + StartWithLastProfile=1 + ''; - [General] - StartWithLastProfile=1 - ''; - - ".mozilla/firefox/user.js".symlink.target = ./user.js; - }; + fs.".mozilla/firefox/user.js".symlink.target = ./user.js; + fs.".mozilla/firefox/default/search.json.mozlz4".symlink.target = let + drv = pkgs.stdenvNoCC.mkDerivation { + # Mozilla uses a custom compression scheme for `search.json` because they're ASSHOLES. + # seriously, why do you need to compress this 2 KiB file? and then why do you need to INVENT YOUR OWN COMPRESSION FORMAT FOR THAT? + # GET YOUR HEAD OUT OF YOUR ASS. + name = "search.json.mozlz4"; + src = ./.; + nativeBuildInputs = with pkgs; [ mozlz4a ]; + buildPhase = '' + mozlz4a ./search.json search.json.mozlz4 + ''; + installPhase = '' + install -D search.json.mozlz4 "$out"/search.json.mozlz4 + ''; + }; + in "${drv}/search.json.mozlz4"; # flush the cache to disk to avoid it taking up too much tmp. persist.byPath = let @@ -298,7 +311,81 @@ in ; in { ".cache/mozilla".store = maybePersist; - ".mozilla/firefox/default".store = maybePersist; + # storage consumes 80+ MB + # the other profile dirs take significantly less; < 20MB total + ".mozilla/firefox/default/storage".store = maybePersist; + # profile files (.mozilla/firefox/default/...): + # - addons.json + # - regenerated on launch + # - addonStartup.json.lz4 + # - regenerated on next-next launch + # - bookmarkbackups/ + # - bounce-tracking-protection.sqlite + # - recreated on launch + # - cert9.db + # - regenerated on launch + # - compatibility.ini + # - regenerated on launch + # - containers.json + # - regenerated on launch + # - content-prefs.sqlite + # - recreated on launch + # - cookies.sqlite{,-wal} + # - recreated on launch + # - crashes/ + # - datareporting/ + # - domain_to_categories.sqlite{,-journal} + # - recreated on launch + # - enumerate_devices.txt + # - recreated on launch + # - extension-preferences.json + # - NOT recreated, but inconsequential to delete + # - extension-settings.json + # - regenerated on launch + # - extension-store/ + # - extension-store-menus/ + # - extensions/ + # - extensions.json + # - regenerated on launch + # - failover.jsc + # - regenerated on launch + # - favicons.sqlite{,-wal} + # - regenerated on launch + # - formhistory.sqlite + # - recreated on launch + # - handlers.json + # - NOT recreated, but inconsequential to delete + # - key4.db + # - recreated on launch + # - lock -> ... + # - minidumps/ + # - permissions.sqlite + # - recreated on launch + # - pkcs11.txt + # - regenerated on launch + # - places.sqlite{,-wal} + # - recreated on launch + # - prefs.js + # - recreated on launch + # - protections.sqlite + # - recreated on launch + # - search.json.mozlz4 + # - recreated on launch; loses any customized search engines + # - security_state/ + # - serviceworker.txt + # - NOT recreated, but inconsequential to delete + # - sessionCheckpoints.json + # - recreated on launch + # - shield-preference-experiments.json + # - NOT recreated, but inconsequential to delete + # - storage/ + # - storage-sync-v2.sqlite + # - recreated on launch + # - storage.sqlite + # - times.json + # - recreated on launch + # - xulstore.json + # - recreated on launch }; }; } diff --git a/hosts/common/programs/firefox/search.json b/hosts/common/programs/firefox/search.json new file mode 100644 index 000000000..2fe897464 --- /dev/null +++ b/hosts/common/programs/firefox/search.json @@ -0,0 +1,83 @@ +{ + "version": 12, + "engines": [ + { + "id": "google", + "_name": "Google", + "_isAppProvided": true, + "_metaData": { + "order": 1 + } + }, + { + "id": "bing", + "_name": "Bing", + "_isAppProvided": true, + "_metaData": { + "order": 2 + } + }, + { + "id": "ddg", + "_name": "DuckDuckGo", + "_isAppProvided": true, + "_metaData": { + "order": 3 + } + }, + { + "id": "wikipedia", + "_name": "Wikipedia (en)", + "_isAppProvided": true, + "_metaData": { + "order": 4 + } + }, + { + "id": "search@kagi.comdefault", + "_name": "Kagi", + "_loadPath": "[addon]search@kagi.com", + "_iconMapObj": { + "16": "moz-extension://8866e489-faf9-4122-a9a4-4845afbc578f/icons/icon_16px.png", + "32": "moz-extension://8866e489-faf9-4122-a9a4-4845afbc578f/icons/icon_32px.png", + "48": "moz-extension://8866e489-faf9-4122-a9a4-4845afbc578f/icons/favicon-48.png", + "180": "moz-extension://8866e489-faf9-4122-a9a4-4845afbc578f/icons/icon_180px.png" + }, + "_metaData": { + "order": 5, + "loadPathHash": "cvZ7LzXkcfkHdmbuYpDRqhvLSfZPgPO0CxObgIPkYU0=" + }, + "_urls": [ + { + "params": [], + "rels": [], + "template": "https://kagi.com/search?q={searchTerms}" + }, + { + "params": [], + "rels": [], + "template": "https://kagi.com/api/autosuggest?q={searchTerms}", + "type": "application/x-suggestions+json" + } + ], + "_orderHint": null, + "_telemetryId": null, + "_filePath": null, + "_definedAliases": [ + "@kagi" + ], + "_extensionID": "search@kagi.com" + } + ], + "metaData": { + "locale": "en-US", + "region": "unknown", + "channel": "default", + "experiment": "", + "distroID": "nixos", + "appDefaultEngineId": "google", + "useSavedOrder": true, + "defaultEngineId": "search@kagi.comdefault", + "defaultEngineIdHash": "hrzTeftqb+2F9OI3GYJwG6XAMryJr8Eut/3f90YKv3k=" + } +}