From 75a6e6c15d2e6710a4cf9a253ba8d55adde7d9dc Mon Sep 17 00:00:00 2001 From: Andrew Lorimer Date: Tue, 20 Aug 2019 18:23:52 +1000 Subject: [PATCH] add build system --- Makefile | 8 +++ README.md | 2 +- build.sh | 124 +++++++++++++++++++++++++++++++++++++++++++++++ build/newtab.zip | Bin 0 -> 12459 bytes 4 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 Makefile create mode 100644 build.sh create mode 100644 build/newtab.zip diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0c1d375 --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +TARGETS := extension +.PHONY: all clean + +all: $(TARGETS) +clean: + rm build/*.crx +extension: + ./build.sh -s src -p newtab.pem -d build/newtab.crx diff --git a/README.md b/README.md index c557cdc..9b4e7aa 100644 --- a/README.md +++ b/README.md @@ -32,4 +32,4 @@ Opening the crx file using Chrome's default file handler causes a "CRX_REQUIRED_ ## Building -For the time being you can run the extension as a local "unpacked" extension, but if you make modifications you may like to make a distributible crx file. +For the time being you can run the extension as a local "unpacked" extension, but if you make modifications you may like to make a distributible crx file. You can do this with the included build script - just run `make all` in the root directory. diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..044c712 --- /dev/null +++ b/build.sh @@ -0,0 +1,124 @@ +# Purpose: Pack a Chromium extension directory into crx3 format +# +# Sources: +# https://stackoverflow.com/a/18709204 +# https://cs.chromium.org/chromium/src/components/crx_file/crx3.proto?l=1&rcl=09de3b4e1e13cf10e431ba119b179169cde289fe +# +# Modified by Andrew Lorimer, August 2019 +# + +description="\e[34m$(basename "$0")\e[0m +Pack a Chromium extension into CRX3 format + +" +usageshort="\e[1mUSAGE:\e[0m + $(basename "$0") [-s src_dir] [-p private_key] [-d output.crx]\n" +usage=" +\e[1mOPTIONS:\e[0m + -s, --source + Directory containing all source files to be included in extension. + Default: ./src + + -d, --destination + Name of a file where generated crx file will be placed. Extisting files will be overwritten. + Default: ./build/extension.crx + + -p, --private + Location of the private key file. + Default: ./extension.pem + + -n, --name + Use this as the file name instead of \"extension\" in the above file paths. + + -h, --help + Show this help message\n" + +dir="$(pwd -P)/src" +name=$(basename $(pwd -P)) +key=$(pwd -P)/$name.pem + +while [ $# -gt 0 ]; do + case "$1" in + -h|--help) + printf "$description$usageshort$usage" + exit + ;; + -s|--source) + dir=(${2-}) + echo "Using source directory $dir" + shift + ;; + -d|--destination) + out=(${2-}) + echo "Generating crx output at $out" + shift + ;; + -p|--private) + key=(${2-}) + shift + ;; + -n|--name) + name=(${2-}) + shift + ;; + --) + break + ;; + *) + printf "\x1b[31mInvalid argument $1\x1b[0m\n\n" + printf "$usageshort" + exit 1 + ;; + esac + shift +done + +if [ -z $out ]; then out="$name.crx"; fi +pub="$name.pub" +sig="$name.sig" +zip="$name.zip" +tosign="$name.presig" +binary_crx_id="$name.crxid" +trap 'rm -f "$pub" "$sig" "$zip" "$tosign" "$binary_crx_id"' EXIT + +printf "Building $(realpath --relative-to=`pwd` $dir) to $(realpath --relative-to=`pwd` $out) with private key $(realpath --relative-to=`pwd` $key)\n" + +# Zip crx directory +printf "\tZipping source directory\n" +cwd=$(pwd -P) +(cd "$dir" && zip -qr -9 -X "$cwd/$zip" .) + + +# Extract crx id +printf "\tExtracting crx id\n" +{ + openssl rsa -in "$key" -pubout -outform der | openssl dgst -sha256 -binary -out "$binary_crx_id" +} &> /dev/null +truncate -s 16 "$binary_crx_id" + +# Generate file to sign +printf "\tSigning crx file\n" +( + printf "CRX3 SignedData" + echo "00 12 00 00 00 0A 10" | xxd -r -p + cat "$binary_crx_id" "$zip" +) > "$tosign" + +openssl dgst -sha256 -binary -sign "$key" < "$tosign" > "$sig" # Signature +openssl rsa -pubout -outform DER < "$key" > "$pub" 2>/dev/null # Public key + +crmagic_hex="43 72 32 34" # Cr24 +version_hex="03 00 00 00" # 3 +header_length="45 02 00 00" +header_chunk_1="12 AC 04 0A A6 02" +header_chunk_2="12 80 02" +header_chunk_3="82 F1 04 12 0A 10" +( + echo "$crmagic_hex $version_hex $header_length $header_chunk_1" | xxd -r -p + cat "$pub" + echo "$header_chunk_2" | xxd -r -p + cat "$sig" + echo "$header_chunk_3" | xxd -r -p + cat "$binary_crx_id" "$zip" +) > "$out" +printf "\tWrote $out\n" diff --git a/build/newtab.zip b/build/newtab.zip new file mode 100644 index 0000000000000000000000000000000000000000..c75da3971f3c8c0b16586a151ddfea861f90fc59 GIT binary patch literal 12459 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 literal 0 HcmV?d00001 -- 2.47.1