#!/bin/sh
# Metadata:
# - Author: Eric Pruitt (https://www.codevat.com)
# - License: 2-Clause BSD
set -e -m -u -o noclobber
trap cleanup EXIT

# X11 screen specification for virtual display.
XEPHYR_SCREEN="1024x1024"
# Temporary directory.
TMPDIR="${TMPDIR:-/tmp}"
# Command used to process strace output
STRACE_FILTER="egrep -o '.*clients2.*|htons.*inet_(addr|pton)\\([^)]+\\)|$'"

# Cleanup resources used by this script.
#
cleanup()
{
    rm -f -r "${pipe:-}" "${user_data_dir:-}"
    kill $(jobs -p) > /dev/null 2>&1 || :
    wait
}

# Write a message to standard error and return a non-zero status. If the exit
# status of the command executed before this function was non-zero, that value
# is returned. Otherwise, 1 is returned.
#
# Arguments:
# - $@: Error message.
#
die()
{
    last_exit_status="$?"
    echo "$*" >&2
    test "$0: $last_exit_status" -ne 0 || return 1
    return "$last_exit_status"
}

# Echo a string of random characters that are POSIX-shell safe and
# getopt(3)-safe.
#
random_shell_safe_name()
{
    tr -c -d "a-zA-Z0-9" < /dev/urandom | head -c16
}

# Run the Chromium wrapper handling user data directory creation, running
# strace for the progenitor process and providing syntactic sugar for closing
# the browser.
#
# Arguments:
# - $@: Chromium command line arguments or "--close" to close the browser.
#
chromium()
{
    if [ "${1:-}" = "--close" ]; then
        xdotool key "alt+F4" && wait
    elif [ -z "${chromium_session_started:-}" ]; then
        user_data_dir="$TMPDIR/user-data-dir.$(random_shell_safe_name)"
        mkdir "$user_data_dir"
        strace -s 256 -y -t -f -e connect,sendto,recvfrom -o "|$STRACE_FILTER" \
        ./chromium.sh --disable-gpu --no-sandbox \
            --user-data-dir="$user_data_dir" "$@" &
        chromium_session_started="x"
    else
        ./chromium.sh --disable-gpu --no-sandbox \
            --user-data-dir="$user_data_dir" "$@"
    fi
}

# Run Xephyr and set the DISPLAY variable if it successfully starts.
#
setup_display()
{
    # If Xephyr fails to start, reading from the pipe will return EOF
    # (read(3p)) which will cause the read command to error (POSIX - Utilities
    # - "read").
    pipe="$TMPDIR/displayfd.$(random_shell_safe_name)"
    mkfifo -m 600 "$pipe"
    Xephyr -br -terminate -screen "$XEPHYR_SCREEN" -displayfd 3 3> "$pipe" &
    read display_number < "$pipe"
    export DISPLAY=":$display_number"
}

main()
{
    setup_display

    # Commands to run the browser and using things like xdotool to manipulate
    # the browser go here. In the following example, the browser is opened on
    # www.codevat.com, then sent to chrome://settings:
    #
    #   chromium
    #   sleep 5
    #   xdotool key "ctrl+l"
    #   xdotool type --delay=10 "chrome://settings/"
    #   xdotool key "Return"
    #   chromium --close
}

test -n "${TMPDIR##-*}" || TMPDIR="./$TMPDIR"
main "${@:-}"
