From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0 ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms11 with LMTPS id aNcSJnBcnF+nHQAA0tVLHw (envelope-from ) for ; Fri, 30 Oct 2020 18:33:20 +0000 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0 with LMTPS id eAHsIXBcnF86QwAA1q6Kng (envelope-from ) for ; Fri, 30 Oct 2020 18:33:20 +0000 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 070F094042E for ; Fri, 30 Oct 2020 18:33:20 +0000 (UTC) Received: from localhost ([::1]:46602 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kYZDD-00054J-0i for larch@yhetil.org; Fri, 30 Oct 2020 14:33:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50162) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kYZCw-00053D-PC for guix-patches@gnu.org; Fri, 30 Oct 2020 14:33:02 -0400 Received: from debbugs.gnu.org ([209.51.188.43]:48163) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kYZCw-0008GB-Fe for guix-patches@gnu.org; Fri, 30 Oct 2020 14:33:02 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1kYZCw-0003r8-Bj for guix-patches@gnu.org; Fri, 30 Oct 2020 14:33:02 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#44335] [PATCH 2/2] gnu: Add ublock-origin-chromium. Resent-From: Marius Bakke Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Fri, 30 Oct 2020 18:33:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 44335 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 44335@debbugs.gnu.org Received: via spool by 44335-submit@debbugs.gnu.org id=B44335.160408278114816 (code B ref 44335); Fri, 30 Oct 2020 18:33:02 +0000 Received: (at 44335) by debbugs.gnu.org; 30 Oct 2020 18:33:01 +0000 Received: from localhost ([127.0.0.1]:59708 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kYZCu-0003ql-UT for submit@debbugs.gnu.org; Fri, 30 Oct 2020 14:33:01 -0400 Received: from eggs.gnu.org ([209.51.188.92]:50048) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kYZCp-0003qJ-5k for 44335@debbugs.gnu.org; Fri, 30 Oct 2020 14:32:57 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]:50040) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kYZCj-0008EP-Us for 44335@debbugs.gnu.org; Fri, 30 Oct 2020 14:32:49 -0400 Received: from ti0006q161-1594.bb.online.no ([46.9.75.77]:33700 helo=localhost) by fencepost.gnu.org with esmtpsa (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.82) (envelope-from ) id 1kYZCh-0003J3-Io for 44335@debbugs.gnu.org; Fri, 30 Oct 2020 14:32:49 -0400 From: Marius Bakke Date: Fri, 30 Oct 2020 19:32:32 +0100 Message-Id: <20201030183232.5497-2-marius@gnu.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201030183232.5497-1-marius@gnu.org> References: <20201030182925.5151-1-marius@gnu.org> <20201030183232.5497-1-marius@gnu.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-Spam-Score: -3.3 (---) X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: "Guix-patches" X-Scanner: ns3122888.ip-94-23-21.eu Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=pass (policy=none) header.from=gnu.org; spf=pass (aspmx1.migadu.com: domain of guix-patches-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=guix-patches-bounces@gnu.org X-Spam-Score: -0.51 X-TUID: 4I5JukUW0kRO * gnu/packages/browser-extensions.scm: New file. * gnu/local.mk (GNU_SYSTEM_MODULES): Adjust accordingly. --- gnu/local.mk | 1 + gnu/packages/browser-extensions.scm | 278 ++++++++++++++++++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 gnu/packages/browser-extensions.scm diff --git a/gnu/local.mk b/gnu/local.mk index 4643d05049..f97a0cda78 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -111,6 +111,7 @@ GNU_SYSTEM_MODULES = \ %D%/packages/boost.scm \ %D%/packages/bootloaders.scm \ %D%/packages/bootstrap.scm \ + %D%/packages/browser-extensions.scm \ %D%/packages/build-tools.scm \ %D%/packages/busybox.scm \ %D%/packages/c.scm \ diff --git a/gnu/packages/browser-extensions.scm b/gnu/packages/browser-extensions.scm new file mode 100644 index 0000000000..b6d160bee7 --- /dev/null +++ b/gnu/packages/browser-extensions.scm @@ -0,0 +1,278 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2020 Marius Bakke +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (gnu packages browser-extensions) + #:use-module (gcrypt base16) + #:use-module ((gcrypt hash) #:prefix hash:) + #:use-module (ice-9 iconv) + #:use-module (guix gexp) + #:use-module (guix packages) + #:use-module (gnu packages base) + #:use-module (gnu packages check) + #:use-module (gnu packages chromium) + #:use-module (gnu packages gnupg) + #:use-module (gnu packages tls) + #:use-module (gnu packages xorg) + #:use-module (guix build-system trivial) + + ;; Imports for extension packages. + #:use-module (guix git-download) + #:use-module (guix build-system gnu) + #:use-module ((guix licenses) #:prefix license:) + #:use-module (gnu packages compression) + #:use-module (gnu packages python) + + #:export (make-chromium-extension)) + +;; Chromium requires that each package is signed with a unique key, from which +;; the "extension ID" derives. Currently the package name is used as seed. +(define (make-signing-key seed) + "Return a derivation for a deterministic PKCS #8 private key using SEED." + + (define sha256sum + (bytevector->base16-string (hash:sha256 (string->bytevector seed "UTF-8")))) + + ;; certtool.c wants a 56 byte seed for a 2048 bit key. + (define size 2048) + (define normalized-seed (string-take sha256sum 56)) + + (computed-file (string-append seed "-signing-key.pem") + #~(system* #$(file-append gnutls "/bin/certtool") + "--generate-privkey" + "--key-type=rsa" + "--pkcs8" + ;; Use the provable FIPS-PUB186-4 algorithm for + ;; deterministic results. + "--provable" + "--password=" + "--no-text" + (string-append "--bits=" #$(number->string size)) + (string-append "--seed=" #$normalized-seed) + "--outfile" #$output))) + +(define* (make-crx package #:optional (chromium-output "out")) + ;; XXX: This is terrible. We pull Xorg and Chromium just to pack and + ;; sign an extension. This should be implemented with something lighter + ;; using the protobuf-based protocol (TODO: where is it documented..?). + (define name (package-name package)) + (define version (package-version package)) + (define signing-key (make-signing-key name)) + + (with-imported-modules '((guix build utils)) + (computed-file + (string-append name "-" version ".crx") + #~(begin + (use-modules (guix build utils) + (ice-9 ftw) + (srfi srfi-26)) + (let ((chromium #$(file-append ungoogled-chromium "/bin/chromium")) + (xvfb #$(file-append xorg-server "/bin/Xvfb")) + (packdir (string-append "/tmp/extension/" #$name))) + (mkdir-p (dirname packdir)) + (copy-recursively (ungexp package chromium-output) packdir) + (system (string-append xvfb " :1 &")) + (setenv "DISPLAY" ":1") + (sleep 2) ;give Xorg some time to initialize... + ;; Chromium stores the current time in the .crx Zip archive. + ;; Sidestep that by using "faketime" for determinism. + ;; FIXME (core-updates): faketime is missing an absolute reference + ;; to 'date', hence the need to set PATH. + (setenv "PATH" #$(file-append coreutils "/bin")) + (invoke #$(file-append libfaketime "/bin/faketime") + "2000-01-01 00:00:00" + chromium + "--user-data-dir=/tmp/signing-profile" + (string-append "--pack-extension=" packdir) + (string-append "--pack-extension-key=" #$signing-key)) + (copy-file (string-append packdir ".crx") #$output)))))) + +(define* (package->chromium-json package #:optional (chromium-output "out")) + "Return a derivation that creates a JSON file for PACKAGE, meant to be +consumed by Chromium to make the installed extension visible." + + (define name (package-name package)) + (define version (package-version package)) + (define crx (make-crx package chromium-output)) + + (computed-file (string-append name "-" version ".json") + #~(call-with-output-file #$output + (lambda (port) + ;; Documentation for the JSON format can be found in + ;; extensions/common/extension.h and + ;; chrome/browser/extensions/external_provider_impl.cc. + (format port " +{ + \"external_crx\": \"~a\", + \"external_version\": \"~a\" +} +" + #$crx #$version))))) + + +(define (key->der key) + "Return a derivation for a file representation of KEY in DER format." + (computed-file "der" + #~(system* #$(file-append gnutls "/bin/certtool") + "--load-privkey" #$key + "--pubkey-info" + "--outfile" #$output + "--outder"))) + +(define (gexp-sha256sum file) + "Return a derivation for a base16 representation of the SHA256 checksum +of FILE." + (with-extensions (list guile-gcrypt) + #~(begin + (use-modules (gcrypt base16) (gcrypt hash)) + (format #f (bytevector->base16-string (file-sha256 #$file)))))) + +(define (chromium-json->profile-object json signing-key) + "Return a derivation that installs JSON to the destination searched by +Chromium, using a file name (aka extension ID) derived from SIGNING-KEY." + (define der (key->der signing-key)) + (define checksum (gexp-sha256sum der)) + + (with-imported-modules '((guix build utils)) + (computed-file + "chromium-extension" + #~(begin + (use-modules (guix build utils)) + (define (base16-string->chromium-base16 str) + ;; Translate STR, a hexadecimal string, to a Chromium-style + ;; representation using the letters a-p (where a=0, p=15). + (define s1 "0123456789abcdef") + (define s2 "abcdefghijklmnop") + (let loop ((chars (string->list str)) + (converted '())) + (if (null? chars) + (list->string (reverse converted)) + (loop (cdr chars) (cons (string-ref + s2 (string-index s1 (car chars))) + converted))))) + + (let ((file-name (base16-string->chromium-base16 + (string-take #$checksum 32))) + (extension-directory (string-append #$output + "/share/chromium/extensions"))) + (mkdir-p extension-directory) + (symlink #$json (string-append extension-directory "/" + file-name ".json"))))))) + +(define* (make-chromium-extension p #:optional (output "out")) + "Create a signed \".crx\" file from package P, an unpacked Chromium +extension, and return a derivation for a package that makes the packed +extension visible to Chromium when installed to a Guix profile. + +OUTPUT can be used to specify which output of P contains the Chromium +extension directory." + (package + (inherit p) + (name (string-append (package-name p) "-chromium")) + (build-system trivial-build-system) + (native-inputs '()) + (inputs + `(("extension" ,(chromium-json->profile-object + (package->chromium-json p output) + (make-signing-key (package-name p)))))) + (propagated-inputs '()) + (outputs '("out")) + (arguments + '(#:modules ((guix build utils)) + #:builder + (begin + (use-modules (guix build utils)) + (copy-recursively (assoc-ref %build-inputs "extension") + (assoc-ref %outputs "out"))))))) + + + +(define uassets + (let ((commit "95d609786680bf4cf267b1dff3f429af88040da1")) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/uBlockOrigin/uAssets.git") + (commit commit))) + (file-name (git-file-name "uAssets" (string-take commit 9))) + (sha256 + (base32 + "070v2g0hyxvqv77b6z404hdlggl0sq2bfhsfl4a84k93p9pwwlrq"))))) + +(define ublock-origin + (package + (name "ublock-origin") + (version "1.30.8") + (home-page "https://github.com/gorhill/uBlock") + (source (origin + (method git-fetch) + (uri (git-reference (url home-page) (commit version))) + (file-name (git-file-name name version)) + (sha256 + (base32 + "1y4dq4p4j4qrw6gfdcbpyigqjinqq3jm8r5x9h5ariiv9s8856w7")))) + (build-system gnu-build-system) + ;; XXX: The xpi and firefox outputs are currently unused, but included + ;; for easy testing. + (outputs '("xpi" "firefox" "chromium")) + (arguments + '(#:tests? #f ;no tests + #:allowed-references () + #:phases + (modify-phases (map (lambda (phase) + (assq phase %standard-phases)) + '(set-paths unpack patch-source-shebangs)) + (add-after 'unpack 'link-uassets + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (symlink (string-append (assoc-ref (or native-inputs inputs) + "uassets")) + "../uAssets") + #t)) + (add-after 'unpack 'make-files-writable + (lambda _ + ;; The build system copies some files and later tries + ;; modifying them. + (for-each make-file-writable (find-files ".")) + #true)) + (add-after 'patch-source-shebangs 'build-xpi + (lambda _ + (invoke "./tools/make-firefox.sh" "all"))) + (add-after 'build-xpi 'build-chromium + (lambda _ + (invoke "./tools/make-chromium.sh"))) + (add-after 'build-chromium 'install + (lambda* (#:key outputs #:allow-other-keys) + (let ((firefox (assoc-ref outputs "firefox")) + (xpi (assoc-ref outputs "xpi")) + (chromium (assoc-ref outputs "chromium"))) + (install-file "dist/build/uBlock0.firefox.xpi" + (string-append xpi "/lib/mozilla/extensions")) + (copy-recursively "dist/build/uBlock0.firefox" firefox) + (copy-recursively "dist/build/uBlock0.chromium" chromium) + #true)))))) + (native-inputs + `(("python" ,python-wrapper) + ("uassets" ,uassets) + ("zip" ,zip))) + (synopsis "Block unwanted content from web sites") + (description + "uBlock Origin is a @dfn{wide spectrum blocker} for IceCat and +ungoogled-chromium.") + (license license:gpl3+))) + +(define-public ublock-origin/chromium + (make-chromium-extension ublock-origin "chromium")) -- 2.28.0