This commit is contained in:
elwrcl committed 2026-08-25 06:01:18 +03:00
1 parent b7106ac8e1
commit 275ac3bf3f
2 files changed
+95 -23

No files matched your search

+29 -6
View File
@@ -81,11 +81,8 @@ Then configure it:
package = helium.packages.${pkgs.system}.helium-widevine;
extensions = [
# uBlock Origin — see "Obtaining extensions" below
{
id = "cjpalhdlnbpafiamejdnhcphjbkeiagm";
hash = "sha256-FIbmYVj8cmXce7Vq4h7d2nOjmk4RkCnABmC4y5NDyGk=";
}
# uBlock Origin
{ id = "cjpalhdlnbpafiamejdnhcphjbkeiagm"; }
];
# Added to the wrapper
@@ -118,7 +115,8 @@ The following options are available under `programs.helium`:
| :--------------- | :----------------- | :--------------------- | :------------------------------------------------- |
| `enable` | boolean | `false` | Whether to enable the Helium browser module. |
| `package` | package | `self.packages.helium` | The helium package to use. |
| `extensions` | list of submodules | `[]` | List of extensions to install `{ id, hash }`. |
| `extensions` | list of submodules | `[]` | Extensions to install: `{ id, hash }` (`hash` only needed in `unpacked` mode). |
| `extensionInstallMode` | `"policy"` or `"unpacked"` | `"policy"` | How extensions are installed — see below. |
| `extraFlags` | list of strings | `[]` | Command line arguments passed to the wrapper. |
| `extraPolicies` | attribute set | `{}` | Raw Chromium policies to apply. |
| `preferences` | attribute set | `{}` | Json that will be merged into XDG Config. |
@@ -157,8 +155,33 @@ find all the json keys and values inside the helium browser by typing
}
```
## Extension install modes
`extensionInstallMode = "policy"` (the default) force-installs every entry in
`extensions` through the `ExtensionInstallForcelist` Chromium policy. The
browser downloads and installs each extension itself, so:
- the real Web Store ID and signature are kept — native messaging hosts such as
KeePassXC-Browser match on that ID and only work this way,
- the install is recorded in the profile, so each extension's `onInstalled`
handler runs once instead of on every launch,
- extensions keep updating themselves.
This mode needs the NixOS module, which is what writes the policy file into
`/etc/chromium/policies/managed/`. No `hash` is required.
`extensionInstallMode = "unpacked"` pins the CRXs in the Nix store and hands
them to the browser with `--load-extension`. It is fully reproducible and needs
no NixOS module, but Chromium treats command-line extensions as freshly
installed on every start — every extension re-runs its `onInstalled` handler,
which for many extensions means a welcome tab on each launch — and it derives
the extension ID from the load path unless the manifest carries a `key`. Each
entry needs a `hash` in this mode; see below.
## Obtaining extensions
Only needed for `extensionInstallMode = "unpacked"`.
> [!WARNING]
> Be wary that if you are rate-limited that the file will be empty and the build will fail
+66 -17
View File
@@ -48,14 +48,23 @@ let
rm -rf $out/_metadata
'';
resolvedExtensions = map (spec: {
inherit (spec) id;
unpacked = unpackExtension { inherit (spec) id hash; };
}) cfg.extensions;
unpackedMode = cfg.extensionInstallMode == "unpacked";
resolvedExtensions = lib.optionals unpackedMode (
map (spec: {
inherit (spec) id;
unpacked = unpackExtension { inherit (spec) id hash; };
}) cfg.extensions
);
webStoreUpdateUrl = "https://clients2.google.com/service/update2/crx";
policyAttrs = {
ExtensionInstallAllowlist = map (ext: ext.id) cfg.extensions;
}
// lib.optionalAttrs (!unpackedMode && cfg.extensions != [ ]) {
ExtensionInstallForcelist = map (ext: "${ext.id};${webStoreUpdateUrl}") cfg.extensions;
}
// cfg.extraPolicies;
extensionRoot = "${config.xdg.dataHome}/helium/extensions";
@@ -103,12 +112,42 @@ in
lib.types.submodule {
options = {
id = lib.mkOption { type = lib.types.str; };
hash = lib.mkOption { type = lib.types.str; };
hash = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
CRX hash, only needed when extensionInstallMode is "unpacked".
'';
};
};
}
);
default = [ ];
};
extensionInstallMode = lib.mkOption {
type = lib.types.enum [
"policy"
"unpacked"
];
default = "policy";
description = ''
How `extensions` reach the browser.
"policy" force-installs them through the ExtensionInstallForcelist
Chromium policy. The browser downloads each extension itself, so the
Web Store IDs and signatures are preserved (native messaging hosts
such as KeePassXC depend on the real ID), the install is recorded in
the profile, and extensions keep updating themselves. Requires the
NixOS module so the policy file lands in /etc/chromium/policies.
"unpacked" pins the CRXs in the Nix store and passes them via
--load-extension. It is reproducible and works without the NixOS
module, but Chromium treats command-line extensions as freshly
installed on every start, which re-fires each extension's onInstalled
handler (welcome tabs on every launch), and derives IDs from the load
path unless the manifest carries a "key".
'';
};
prodversion = lib.mkOption {
type = lib.types.str;
default = "151.0.0.0";
@@ -157,6 +196,14 @@ in
};
config = lib.mkIf cfg.enable {
assertions = map (ext: {
assertion = ext.hash != null;
message = ''
programs.helium.extensions."${ext.id}".hash is required when
programs.helium.extensionInstallMode = "unpacked".
'';
}) (lib.optionals unpackedMode cfg.extensions);
home = {
packages = [
heliumWithFlags
@@ -165,18 +212,20 @@ in
];
activation = {
# Refresh the writable copies the --load-extension flag points at. The
# tree is rebuilt from scratch so extensions that were removed from the
# config, or whose store path changed, do not linger.
heliumExtensions = lib.mkIf (resolvedExtensions != [ ]) (
lib.hm.dag.entryAfter [ "writeBoundary" ] ''
run rm -rf ${lib.escapeShellArg extensionRoot}
run mkdir -p ${lib.escapeShellArg extensionRoot}
${lib.concatMapStringsSep "\n" (ext: ''
run cp -r ${ext.unpacked} ${lib.escapeShellArg "${extensionRoot}/${ext.id}"}
'') resolvedExtensions}
run chmod -R u+w ${lib.escapeShellArg extensionRoot}
''
heliumExtensions = lib.hm.dag.entryAfter [ "writeBoundary" ] (
if resolvedExtensions != [ ] then
''
run rm -rf ${lib.escapeShellArg extensionRoot}
run mkdir -p ${lib.escapeShellArg extensionRoot}
${lib.concatMapStringsSep "\n" (ext: ''
run cp -r ${ext.unpacked} ${lib.escapeShellArg "${extensionRoot}/${ext.id}"}
'') resolvedExtensions}
run chmod -R u+w ${lib.escapeShellArg extensionRoot}
''
else
''
run rm -rf ${lib.escapeShellArg extensionRoot}
''
);
heliumPreferences = lib.mkIf (cfg.preferences != { }) (