From eedee46f2fff823147d1b9aaa767397737bdea11 Mon Sep 17 00:00:00 2001 From: Luis Hebendanz Date: Sun, 28 Jun 2020 15:55:07 +0200 Subject: [PATCH 1/7] Adding nix firefox extension support --- .../networking/browsers/firefox/wrapper.nix | 196 +++++++++++++++++- 1 file changed, 194 insertions(+), 2 deletions(-) diff --git a/pkgs/applications/networking/browsers/firefox/wrapper.nix b/pkgs/applications/networking/browsers/firefox/wrapper.nix index cc6cc72e27b..5f4ce80bd7a 100644 --- a/pkgs/applications/networking/browsers/firefox/wrapper.nix +++ b/pkgs/applications/networking/browsers/firefox/wrapper.nix @@ -1,4 +1,6 @@ -{ stdenv, lib, makeDesktopItem, makeWrapper, lndir, config +{ stdenv, lib, makeDesktopItem, makeWrapper, lndir, config, + +replace, fetchurl, zip, unzip, jq ## various stuff that can be plugged in , flashplayer, hal-flash @@ -31,6 +33,12 @@ let , forceWayland ? false , useGlvnd ? true , cfg ? config.${browserName} or {} + + ## Following options are needed for extra prefs & policies + , extraPrefs ? "" + , extraPolicies ? {} + , firefoxLibName ? "firefox" + , extraExtensions ? [ ] }: assert forceWayland -> (browser ? gtk3); # Can only use the wayland backend if gtk3 is being used @@ -81,6 +89,88 @@ let ++ pkcs11Modules; gtk_modules = [ libcanberra-gtk2 ]; + ######################### + # # + # EXTRA PREF CHANGES # + # # + ######################### + policiesJson = builtins.toFile "policies.json" + (builtins.toJSON enterprisePolicies); + + extensions = builtins.map (a: + if ! (builtins.hasAttr "name" a) || ! (builtins.isString a.name) then + throw "Firefox addon needs a name attribute" + else if ! (builtins.hasAttr "url" a) || ! (builtins.isString a.url) then + throw "Addon ${a.pname} needs an url" + else if ! (builtins.hasAttr "sha256" a) || ! (builtins.isString a.sha256) then + throw "Addon ${a.pname} needs an sha256 checksum" + else stdenv.mkDerivation rec { + pname = a.name; + version = "1.0"; + src = fetchurl { + url = a.url; + sha256 = a.sha256; + }; + + phases = [ "buildPhase" ]; + + extid = "${a.sha256}@${a.name}"; + + buildInputs = [ zip unzip jq ]; + + buildPhase = '' + UUID="${extid}" + mkdir -p "$out/$UUID" + unzip -q ${src} -d "$out/$UUID" + NEW_MANIFEST=$(jq '. + {"applications": { "gecko": { "id": "${extid}" }}, "browser_specific_settings":{"gecko":{"id": "${extid}"}}}' "$out/$UUID/manifest.json") + echo "$NEW_MANIFEST" > "$out/$UUID/manifest.json" + cd "$out/$UUID" + zip -r -q -FS "$out/$UUID.xpi" * + rm -r "$out/$UUID" + ''; + } + ) extraExtensions; + + enterprisePolicies = + { + policies = { + DisableAppUpdate = true; + } // + { + ExtensionSettings = { + "*" = { + blocked_install_message = "You can't have manual extension mixed with nix extensions"; + installation_mode = "blocked"; + }; + + } // lib.foldr (e: ret: + ret // { + "${e.extid}" = { + installation_mode = "allowed"; + }; + } + ) {} extensions; + } + // extraPolicies; + }; + + mozillaCfg = builtins.toFile "mozilla.cfg" '' +// First line must be a comment + + // Disables addon signature checking + // to be able to install addons that do not have an extid + // Security is maintained because only user whitelisted addons + // with a checksum can be installed + lockPref("xpinstall.signatures.required", false); + ${extraPrefs} + ''; + + ############################# + # # + # END EXTRA PREF CHANGES # + # # + ############################# + in stdenv.mkDerivation { inherit pname version; @@ -106,6 +196,7 @@ let nativeBuildInputs = [ makeWrapper lndir ]; buildInputs = lib.optional (browser ? gtk3) browser.gtk3; + buildCommand = lib.optionalString stdenv.isDarwin '' mkdir -p $out/Applications cp -R --no-preserve=mode,ownership ${browser}/Applications/${browserName}.app $out/Applications @@ -117,7 +208,66 @@ let exit 1 fi - makeWrapper "$(readlink -v --canonicalize-existing "${browser}${browser.execdir or "/bin"}/${browserName}")" \ + ######################### + # # + # EXTRA PREF CHANGES # + # # + ######################### + # Link the runtime. The executable itself has to be copied, + # because it will resolve paths relative to its true location. + # Any symbolic links have to be replicated as well. + cd "${browser}" + find . -type d -exec mkdir -p "$out"/{} \; + + find . -type f \( -not -name "${browserName}" \) -exec ln -sT "${browser}"/{} "$out"/{} \; + + find . -type f -name "${browserName}" -print0 | while read -d $'\0' f; do + cp -P --no-preserve=mode,ownership "${browser}/$f" "$out/$f" + chmod a+rwx "$out/$f" + done + + # fix links and absolute references + cd "${browser}" + + find . -type l -print0 | while read -d $'\0' l; do + target="$(readlink "$l" | ${replace}/bin/replace-literal -es -- "${browser}" "$out")" + ln -sfT "$target" "$out/$l" + done + + # This will not patch binaries, only "text" files. + # Its there for the wrapper mostly. + cd "$out" + ${replace}/bin/replace-literal -esfR -- "${browser}" "$out" + + # create the wrapper + + executablePrefix="$out${browser.execdir or "/bin"}" + executablePath="$executablePrefix/${browserName}" + + if [ ! -x "$executablePath" ] + then + echo "cannot find executable file \`${browser}${browser.execdir or "/bin"}/${browserName}'" + exit 1 + fi + + if [ ! -L "$executablePath" ] + then + # Careful here, the file at executablePath may already be + # a wrapper. That is why we postfix it with -old instead + # of -wrapped. + oldExe="$executablePrefix"/".${browserName}"-old + mv "$executablePath" "$oldExe" + else + oldExe="$(readlink -v --canonicalize-existing "$executablePath")" + fi + + if [ ! -x "${browser}${browser.execdir or "/bin"}/${browserName}" ] + then + echo "cannot find executable file \`${browser}${browser.execdir or "/bin"}/${browserName}'" + exit 1 + fi + + makeWrapper "$oldExe" \ "$out${browser.execdir or "/bin"}/${browserName}${nameSuffix}" \ --suffix-each MOZ_PLUGIN_PATH ':' "$plugins" \ --suffix LD_LIBRARY_PATH ':' "$libs" \ @@ -137,6 +287,11 @@ let --suffix XDG_DATA_DIRS : '${gnome3.adwaita-icon-theme}/share' '' } + ############################# + # # + # END EXTRA PREF CHANGES # + # # + ############################# if [ -e "${browser}/share/icons" ]; then mkdir -p "$out/share" @@ -166,6 +321,43 @@ let # For manpages, in case the program supplies them mkdir -p $out/nix-support echo ${browser} > $out/nix-support/propagated-user-env-packages + + + ######################### + # # + # EXTRA PREF CHANGES # + # # + ######################### + # user customization + mkdir -p $out/lib/${firefoxLibName} + + # creating policies.json + mkdir -p "$out/lib/${firefoxLibName}/distribution" + + POL_PATH="$out/lib/${firefoxLibName}/distribution/policies.json" + rm -f "$POL_PATH" + cat ${policiesJson} >> "$POL_PATH" + + # preparing for autoconfig + mkdir -p "$out/lib/${firefoxLibName}/defaults/pref" + + cat > "$out/lib/${firefoxLibName}/defaults/pref/autoconfig.js" < "$out/lib/${firefoxLibName}/mozilla.cfg" < ${mozillaCfg} + + mkdir -p $out/lib/${firefoxLibName}/distribution/extensions + + for i in ${toString extensions}; do + ln -s -t $out/lib/${firefoxLibName}/distribution/extensions $i/* + done + ############################# + # # + # END EXTRA PREF CHANGES # + # # + ############################# ''; preferLocalBuild = true; From 397597f731de70130ee3949a22c99c6236c16c06 Mon Sep 17 00:00:00 2001 From: Luis Hebendanz Date: Mon, 30 Nov 2020 16:30:46 +0100 Subject: [PATCH 2/7] Added fetchfirefoxaddon --- .../networking/browsers/firefox/wrapper.nix | 41 ++++--------------- .../fetchfirefoxaddon/default.nix | 38 +++++++++++++++++ pkgs/top-level/all-packages.nix | 2 + 3 files changed, 49 insertions(+), 32 deletions(-) create mode 100644 pkgs/build-support/fetchfirefoxaddon/default.nix diff --git a/pkgs/applications/networking/browsers/firefox/wrapper.nix b/pkgs/applications/networking/browsers/firefox/wrapper.nix index 5f4ce80bd7a..a95e871b306 100644 --- a/pkgs/applications/networking/browsers/firefox/wrapper.nix +++ b/pkgs/applications/networking/browsers/firefox/wrapper.nix @@ -35,9 +35,13 @@ let , cfg ? config.${browserName} or {} ## Following options are needed for extra prefs & policies + # For more information about anti tracking (german website) + # vist https://wiki.kairaven.de/open/app/firefo , extraPrefs ? "" + # For more information about policies visit + # https://github.com/mozilla/policy-templates#enterprisepoliciesenabled , extraPolicies ? {} - , firefoxLibName ? "firefox" + , firefoxLibName ? "firefox" # Important for tor package or the like , extraExtensions ? [ ] }: @@ -98,37 +102,10 @@ let (builtins.toJSON enterprisePolicies); extensions = builtins.map (a: - if ! (builtins.hasAttr "name" a) || ! (builtins.isString a.name) then - throw "Firefox addon needs a name attribute" - else if ! (builtins.hasAttr "url" a) || ! (builtins.isString a.url) then - throw "Addon ${a.pname} needs an url" - else if ! (builtins.hasAttr "sha256" a) || ! (builtins.isString a.sha256) then - throw "Addon ${a.pname} needs an sha256 checksum" - else stdenv.mkDerivation rec { - pname = a.name; - version = "1.0"; - src = fetchurl { - url = a.url; - sha256 = a.sha256; - }; - - phases = [ "buildPhase" ]; - - extid = "${a.sha256}@${a.name}"; - - buildInputs = [ zip unzip jq ]; - - buildPhase = '' - UUID="${extid}" - mkdir -p "$out/$UUID" - unzip -q ${src} -d "$out/$UUID" - NEW_MANIFEST=$(jq '. + {"applications": { "gecko": { "id": "${extid}" }}, "browser_specific_settings":{"gecko":{"id": "${extid}"}}}' "$out/$UUID/manifest.json") - echo "$NEW_MANIFEST" > "$out/$UUID/manifest.json" - cd "$out/$UUID" - zip -r -q -FS "$out/$UUID.xpi" * - rm -r "$out/$UUID" - ''; - } + if ! (builtins.hasAttr "extid" a) then + throw "extraExtensions has an invalid entry. Missing extid attribute. Please use fetchfirefoxaddon" + else + a ) extraExtensions; enterprisePolicies = diff --git a/pkgs/build-support/fetchfirefoxaddon/default.nix b/pkgs/build-support/fetchfirefoxaddon/default.nix new file mode 100644 index 00000000000..b199a46e793 --- /dev/null +++ b/pkgs/build-support/fetchfirefoxaddon/default.nix @@ -0,0 +1,38 @@ +{stdenv, lib, coreutils, unzip, jq, zip, fetchurl,writeScript, ...}: +let + +in + { name, + url, + sha256, +}: + +stdenv.mkDerivation rec { + + inherit name; + extid = "${sha256}@${name}"; + passthru = { + exitd=extid; + }; + + builder = writeScript "xpibuilder" '' + source $stdenv/setup + + header "firefox addon $name into $out" + + UUID="${extid}" + mkdir -p "$out/$UUID" + unzip -q ${src} -d "$out/$UUID" + NEW_MANIFEST=$(jq '. + {"applications": { "gecko": { "id": "${extid}" }}, "browser_specific_settings":{"gecko":{"id": "${extid}"}}}' "$out/$UUID/manifest.json") + echo "$NEW_MANIFEST" > "$out/$UUID/manifest.json" + cd "$out/$UUID" + zip -r -q -FS "$out/$UUID.xpi" * + rm -r "$out/$UUID" + ''; + src = fetchurl { + url = url; + sha256 = sha256; + }; + nativeBuildInputs = [ coreutils unzip zip jq ]; +} + diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index ac6bd3343a5..d0c6cb7ecd6 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -365,6 +365,8 @@ in fetchhg = callPackage ../build-support/fetchhg { }; + fetchfirefoxaddon = callPackage ../build-support/fetchfirefoxaddon {}; + # `fetchurl' downloads a file from the network. fetchurl = if stdenv.buildPlatform != stdenv.hostPlatform then buildPackages.fetchurl # No need to do special overrides twice, From 5f8eca5461297a11b4ef42d5f93f47974a300117 Mon Sep 17 00:00:00 2001 From: Luis Hebendanz Date: Mon, 30 Nov 2020 18:49:29 +0100 Subject: [PATCH 3/7] Added missing sha1 and sha512 flags --- pkgs/build-support/fetchfirefoxaddon/default.nix | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pkgs/build-support/fetchfirefoxaddon/default.nix b/pkgs/build-support/fetchfirefoxaddon/default.nix index b199a46e793..c232e4cdace 100644 --- a/pkgs/build-support/fetchfirefoxaddon/default.nix +++ b/pkgs/build-support/fetchfirefoxaddon/default.nix @@ -2,15 +2,19 @@ let in - { name, - url, - sha256, + { + name +, url +, md5 ? "" +, sha1 ? "" +, sha256 ? "" +, sha512 ? "" }: stdenv.mkDerivation rec { inherit name; - extid = "${sha256}@${name}"; + extid = "${src.outputHash}@${name}"; passthru = { exitd=extid; }; @@ -31,7 +35,7 @@ stdenv.mkDerivation rec { ''; src = fetchurl { url = url; - sha256 = sha256; + inherit md5 sha1 sha256 sha512; }; nativeBuildInputs = [ coreutils unzip zip jq ]; } From cc421679e2640f08ef2433504c03fedc3eaac857 Mon Sep 17 00:00:00 2001 From: Luis Hebendanz Date: Tue, 1 Dec 2020 22:07:34 +0100 Subject: [PATCH 4/7] Update pkgs/applications/networking/browsers/firefox/wrapper.nix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jörg Thalheim --- pkgs/applications/networking/browsers/firefox/wrapper.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/applications/networking/browsers/firefox/wrapper.nix b/pkgs/applications/networking/browsers/firefox/wrapper.nix index a95e871b306..674ca3c86c9 100644 --- a/pkgs/applications/networking/browsers/firefox/wrapper.nix +++ b/pkgs/applications/networking/browsers/firefox/wrapper.nix @@ -36,7 +36,7 @@ let ## Following options are needed for extra prefs & policies # For more information about anti tracking (german website) - # vist https://wiki.kairaven.de/open/app/firefo + # visit https://wiki.kairaven.de/open/app/firefox , extraPrefs ? "" # For more information about policies visit # https://github.com/mozilla/policy-templates#enterprisepoliciesenabled From b89c0fcebd6ed64e84bd26e15379fd4c22b01b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 2 Dec 2020 09:48:42 +0100 Subject: [PATCH 5/7] fetchFirefoxAddon: rename to use camelCase --- pkgs/top-level/all-packages.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index d0c6cb7ecd6..a8061f8c19e 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -365,7 +365,7 @@ in fetchhg = callPackage ../build-support/fetchhg { }; - fetchfirefoxaddon = callPackage ../build-support/fetchfirefoxaddon {}; + fetchFirefoxAddon = callPackage ../build-support/fetchfirefoxaddon {}; # `fetchurl' downloads a file from the network. fetchurl = if stdenv.buildPlatform != stdenv.hostPlatform From 9712bbdf7454be4f35a290bc2be23042dff8c60d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 2 Dec 2020 09:50:59 +0100 Subject: [PATCH 6/7] firefoxaddon: formatting nitpicks --- pkgs/applications/networking/browsers/firefox/wrapper.nix | 5 ++--- pkgs/build-support/fetchfirefoxaddon/default.nix | 7 +------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/pkgs/applications/networking/browsers/firefox/wrapper.nix b/pkgs/applications/networking/browsers/firefox/wrapper.nix index 674ca3c86c9..f9b7f2bb8a2 100644 --- a/pkgs/applications/networking/browsers/firefox/wrapper.nix +++ b/pkgs/applications/networking/browsers/firefox/wrapper.nix @@ -1,6 +1,5 @@ -{ stdenv, lib, makeDesktopItem, makeWrapper, lndir, config, - -replace, fetchurl, zip, unzip, jq +{ stdenv, lib, makeDesktopItem, makeWrapper, lndir, config +, replace, fetchurl, zip, unzip, jq ## various stuff that can be plugged in , flashplayer, hal-flash diff --git a/pkgs/build-support/fetchfirefoxaddon/default.nix b/pkgs/build-support/fetchfirefoxaddon/default.nix index c232e4cdace..3426743b2cf 100644 --- a/pkgs/build-support/fetchfirefoxaddon/default.nix +++ b/pkgs/build-support/fetchfirefoxaddon/default.nix @@ -1,16 +1,11 @@ {stdenv, lib, coreutils, unzip, jq, zip, fetchurl,writeScript, ...}: -let - -in - { - name +{ name , url , md5 ? "" , sha1 ? "" , sha256 ? "" , sha512 ? "" }: - stdenv.mkDerivation rec { inherit name; From 7c8994e40e411d5b0a151b3891a57a73006d0e8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 2 Dec 2020 09:49:43 +0100 Subject: [PATCH 7/7] doc/firefox: initial documentation --- doc/builders/packages/firefox.section.md | 40 ++++++++++++++++++++++++ doc/builders/packages/index.xml | 1 + 2 files changed, 41 insertions(+) create mode 100644 doc/builders/packages/firefox.section.md diff --git a/doc/builders/packages/firefox.section.md b/doc/builders/packages/firefox.section.md new file mode 100644 index 00000000000..2f89da2d459 --- /dev/null +++ b/doc/builders/packages/firefox.section.md @@ -0,0 +1,40 @@ +# Firefox + +## Build wrapped Firefox with extensions and policies + +The `wrapFirefox` function allows to pass policies, preferences and extension that are available to firefox. With the help of `fetchFirefoxAddon` this allows build a firefox version that already comes with addons pre-installed: + +```nix +{ + myFirefox = wrapFirefox firefox-unwrapped { + extraExtensions = [ + (fetchFirefoxAddon { + name = "ublock"; + url = "https://addons.mozilla.org/firefox/downloads/file/3679754/ublock_origin-1.31.0-an+fx.xpi"; + sha256 = "1h768ljlh3pi23l27qp961v1hd0nbj2vasgy11bmcrlqp40zgvnr"; + }) + ]; + + extraPolicies = { + CaptivePortal = false; + DisableFirefoxStudies = true; + DisablePocket = true; + DisableTelemetry = true; + DisableFirefoxAccounts = true; + FirefoxHome = { + Pocket = false; + Snippets = false; + }; + UserMessaging = { + ExtensionRecommendations = false; + SkipOnboarding = true; + }; + }; + + extraPrefs = '' + // Show more ssl cert infos + lockPref("security.identityblock.show_extended_validation", true); + ''; + }; +} +``` diff --git a/doc/builders/packages/index.xml b/doc/builders/packages/index.xml index 3c9a56a81b7..6d7537bb36d 100644 --- a/doc/builders/packages/index.xml +++ b/doc/builders/packages/index.xml @@ -10,6 +10,7 @@ +