mirror of
https://git.in.rschanz.org/ryan77627/guix.git
synced 2024-12-25 05:48:07 -05:00
Add (gnu build chromium-extension).
* gnu/build/chromium-extension.scm: New file. * gnu/local.mk (GNU_SYSTEM_MODULES): Adjust accordingly.
This commit is contained in:
parent
c103010a4a
commit
d7a295b24b
2 changed files with 193 additions and 0 deletions
192
gnu/build/chromium-extension.scm
Normal file
192
gnu/build/chromium-extension.scm
Normal file
|
@ -0,0 +1,192 @@
|
|||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2020 Marius Bakke <marius@gnu.org>
|
||||
;;;
|
||||
;;; 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (gnu build chromium-extension)
|
||||
#: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)
|
||||
#:export (make-chromium-extension))
|
||||
|
||||
;;; Commentary:
|
||||
;;;
|
||||
;;; Tools to deal with Chromium extensions.
|
||||
;;;
|
||||
;;; Code:
|
||||
|
||||
(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)
|
||||
#:local-build? #t))
|
||||
|
||||
(define* (make-crx signing-key package #:optional (package-output "out"))
|
||||
"Create a signed \".crx\" file from the unpacked Chromium extension residing
|
||||
in PACKAGE-OUTPUT of PACKAGE. The extension will be signed with SIGNING-KEY."
|
||||
(define name (package-name package))
|
||||
(define version (package-version package))
|
||||
|
||||
(with-imported-modules '((guix build utils))
|
||||
(computed-file
|
||||
(string-append name "-" version ".crx")
|
||||
#~(begin
|
||||
;; This is not great. We pull Xorg and Chromium just to Zip and
|
||||
;; sign an extension. This should be implemented with something
|
||||
;; lighter. (TODO: where is the CRXv3 documentation..?)
|
||||
(use-modules (guix build utils))
|
||||
(let ((chromium #$(file-append ungoogled-chromium "/bin/chromium"))
|
||||
(xvfb #$(file-append xorg-server "/bin/Xvfb"))
|
||||
(packdir "/tmp/extension"))
|
||||
(mkdir-p (dirname packdir))
|
||||
(copy-recursively (ungexp package package-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.
|
||||
;; Use a fixed timestamp for deterministic behavior.
|
||||
;; 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)))
|
||||
#:local-build? #t)))
|
||||
|
||||
(define* (crx->chromium-json crx version)
|
||||
"Return a derivation that creates a Chromium JSON settings file for the
|
||||
extension given as CRX. VERSION is used to signify the CRX version, and
|
||||
must match the version listed in the extension manifest.json."
|
||||
;; See chrome/browser/extensions/external_provider_impl.cc and
|
||||
;; extensions/common/extension.h for documentation on the JSON format.
|
||||
(computed-file "extension.json"
|
||||
#~(call-with-output-file #$output
|
||||
(lambda (port)
|
||||
(format port "{
|
||||
\"external_crx\": \"~a\",
|
||||
\"external_version\": \"~a\"
|
||||
}
|
||||
"
|
||||
#$crx #$version)))
|
||||
#:local-build? #t))
|
||||
|
||||
|
||||
(define (signing-key->public-der key)
|
||||
"Return a derivation for a file containing the public key of KEY in DER
|
||||
format."
|
||||
(computed-file "der"
|
||||
#~(system* #$(file-append gnutls "/bin/certtool")
|
||||
"--load-privkey" #$key
|
||||
"--pubkey-info"
|
||||
"--outfile" #$output
|
||||
"--outder")
|
||||
#:local-build? #t))
|
||||
|
||||
(define (chromium-json->profile-object json signing-key)
|
||||
"Return a derivation that installs JSON to the directory searched by
|
||||
Chromium, using a file name (aka extension ID) derived from SIGNING-KEY."
|
||||
(define der (signing-key->public-der signing-key))
|
||||
|
||||
(with-extensions (list guile-gcrypt)
|
||||
(with-imported-modules '((guix build utils))
|
||||
(computed-file
|
||||
"chromium-extension"
|
||||
#~(begin
|
||||
(use-modules (guix build utils)
|
||||
(gcrypt base16)
|
||||
(gcrypt hash))
|
||||
(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* ((checksum (bytevector->base16-string (file-sha256 #$der)))
|
||||
(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"))))
|
||||
#:local-build? #t))))
|
||||
|
||||
(define* (make-chromium-extension p #:optional (output "out"))
|
||||
"Create a Chromium extension from package P and return a package that,
|
||||
when installed, will make the extension contained in P available as a
|
||||
Chromium browser extension. OUTPUT specifies which output of P to use."
|
||||
(let* ((pname (package-name p))
|
||||
(version (package-version p))
|
||||
(signing-key (make-signing-key pname)))
|
||||
(package
|
||||
(inherit p)
|
||||
(name (string-append pname "-chromium"))
|
||||
(source #f)
|
||||
(build-system trivial-build-system)
|
||||
(native-inputs '())
|
||||
(inputs
|
||||
`(("extension" ,(chromium-json->profile-object
|
||||
(crx->chromium-json (make-crx signing-key p output)
|
||||
version)
|
||||
signing-key))))
|
||||
(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"))))))))
|
|
@ -657,6 +657,7 @@ GNU_SYSTEM_MODULES = \
|
|||
%D%/build/accounts.scm \
|
||||
%D%/build/activation.scm \
|
||||
%D%/build/bootloader.scm \
|
||||
%D%/build/chromium-extension.scm \
|
||||
%D%/build/cross-toolchain.scm \
|
||||
%D%/build/image.scm \
|
||||
%D%/build/file-systems.scm \
|
||||
|
|
Loading…
Reference in a new issue