#!/bin/bash
#determine if chromium is installed
if command -v chromium >/dev/null || command -v chromium-browser >/dev/null || [ -d /snap/chromium ] || [ -d /var/lib/flatpak/app/org.chromium.Chromium ];then
echo "Chromium is installed. Continuing..."
else
error "User error: Chromium is not installed! Failed to find either a 'chromium' command or 'chromium-browser' command. If you are sure Chromium is installed, please reach out to Botspot for this to be fixed."
fi
#determine where the Chromium customizations folder is.
if [ -d /etc/chromium.d ];then
folder=/etc/chromium.d
elif [ -d /snap/chromium ] && [ -f /snap/bin/chromium ];then
#if Snap Chromium is installed, make the customizations folder and later make a script to source its contents
if [ ! -d /etc/chromium.d ];then
sudo mkdir -p /etc/chromium.d
fi
folder=/etc/chromium.d
elif [ -d /etc/chromium-browser/customizations ];then
folder=/etc/chromium-browser/customizations
else
error "User error: Cannot find the directory where Chromium keeps its flags! Usually this would be /etc/chromium.d or /etc/chromium-browser/customizations. On your system, neither of these directories exist. Please reach out to Botspot for this to be fixed."
fi
#Fix edge case where both an old version of chromium and a newer version are installed simultaneously
if [ -d /etc/chromium-browser/customizations ] && [ -d /etc/chromium.d ] && [ ! -L /etc/chromium-browser/customizations ];then
#The $folder variable is /etc/chromium.d, but make /etc/chromium-browser/customizations pick up changes in /etc/chromium.d by using a symlink
status -n "There are two Chromium customization folders on your system: /etc/chromium.d and /etc/chromium-browser/customizations.\nCreating a symlink to keep both locations synchronized..."
#Move any customization files from /etc/chromium-browser/customizations to /etc/chromium.d, without overwriting anything
sudo cp -nr /etc/chromium-browser/customizations /etc/chromium.d && \
sudo rm -rf /etc/chromium-browser/customizations && \
sudo ln -s /etc/chromium.d /etc/chromium-browser/customizations
status_green Done
fi
#if Chromium is installed from Snap or Flatpak, make a script to source the contents of /etc/chromium.d
if [ -d /snap/chromium ] || [ -d /var/lib/flatpak/app/org.chromium.Chromium ];then
if [ -f $HOME/.chromium-browser.init ] && [ "$(sha1sum $HOME/.chromium-browser.init | awk '{print $1}')" != 'cead3a7e98ddd3dbfeea285736c89409a7d426cd' ];then
warning "This script needs to create this file: ~/.chromium-browser.init, but it already exists!"
read -N 1 -p "Enter Y to replace this file, or N to exit now." answer
echo
if [ "$answer" != Y ] && [ "$answer" != y ];then
echo "User error: $HOME/.chromium-browser.init already exists and the user did not want to overwrite it."
exit 1
fi
fi
#The ~/.chromium-browser.init file is the one single entrypoint for running scripts during a Snap Chromium's launch.
#I encountered significant difficulty making this work. Normal Chromium-browser uses bash to source things, but Snap /snap/chromium/2003/bin/chromium.launcher is /bin/sh
cat << "EOF" > $HOME/.chromium-browser.init
#!/bin/sh
eval "$(run-parts --list -- /etc/chromium.d | xargs cat)"
EOF
fi
#detect if dark mode is currently enabled by this tool
if [ -f "${folder}/dark_mode" ];then
dark_mode=TRUE
else
dark_mode=FALSE
fi
#detect if dark mode for all websites is currently enabled by this tool
if [ -f "${folder}/site_dark_mode" ];then
site_dark_mode=TRUE
else
site_dark_mode=FALSE
fi
#detect current UI scale value
if [ -f "${folder}/ui_scale" ];then
ui_scale="$(cat "${folder}/ui_scale" | grep -o '\--force-device-scale-factor=.*' | tr -cd '0123456789.\n')"
else
ui_scale=1.00
fi
#detect if google sync is currently enabled by this tool
if [ -f "${folder}/apikeys" ];then
google_sync=TRUE
else
google_sync=FALSE
fi
#detect if tab previews is currently enabled by this tool
if [ -f "${folder}/tab_previews" ];then
tab_previews=TRUE
else
tab_previews=FALSE
fi
#detect if various performance improvements are currently enabled by this tool
if [ -f "${folder}/performance_improvements" ];then
performance_improvements=TRUE
else
performance_improvements=FALSE
fi
#detect if the reduce_writes script is enabled
if [ -f "${folder}/reduce_writes" ];then
reduce_writes=TRUE
else
reduce_writes=FALSE
fi
#detect if Widevine is enabled
if [ -d /opt/WidevineCdm ];then
widevine=TRUE
else
widevine=FALSE
fi
#detect if Widevine can be enabled
if [ $arch == 32 ];then
widevine_possible=TRUE
widevine_message=(--field="Enable Widevine DRM (for Netflix, Spotify)":CHK "$widevine")
else
widevine_possible=FALSE
widevine_message=()
fi
#Set text of dialog window
text="Better Chromium - by Botspot"
#detect if chromium is running, and if so, remind the user to relaunch it when done
if pgrep chromium >/dev/null || pgrep chromium-browser >/dev/null ;then
text+=$'\n'"Changes will take effect after you relaunch Chromium."
fi
output="$(yad --center --form --width=410 --separator='\n' \
--title="Better Chromium" \
--window-icon="$(dirname "$0")/icon-64.png" \
--text="$text" \
--field="Enable Dark Mode":CHK "$dark_mode" \
--field="Dark Mode for all websites":CHK "$site_dark_mode" \
--field="Click to see more themes:LBL" '' \
--field="UI Scale: (default 1)":NUM "${ui_scale}!0.25..4!0.05!2" \
--field="Tab previews":CHK "$tab_previews" \
--field="Enable Google Sync":CHK "$google_sync" \
--field="Performance Improvements":CHK "$performance_improvements" \
--field="Reduce SD card writes":CHK "$reduce_writes" \
"${widevine_message[@]}")"
button=$?
if [ "$button" != 0 ];then
echo "User error: Exiting now without making any changes."
exit 1
fi
echo "Received values:"
dark_mode="$(sed -n 1p <<<"$output")"
echo "dark_mode: $dark_mode"
site_dark_mode="$(sed -n 2p <<<"$output")"
echo "site_dark_mode: $site_dark_mode"
#skip line 3 because that was an empty field from "Click to see more themes" links
ui_scale="$(sed -n 4p <<<"$output")"
echo "ui_scale: $ui_scale"
tab_previews="$(sed -n 5p <<<"$output")"
echo "tab_previews: $tab_previews"
google_sync="$(sed -n 6p <<<"$output")"
echo "google_sync: $google_sync"
performance_improvements="$(sed -n 7p <<<"$output")"
echo "performance_improvements: $performance_improvements"
reduce_writes="$(sed -n 8p <<<"$output")"
echo "reduce_writes: $reduce_writes"
widevine="$(sed -n 9p <<<"$output")"
echo "widevine: $widevine"
echo
#if user enabled reduce_writes or performance_improvements, and ZRAM is not installed, then recommend the More RAM app
if [ ! -f /usr/bin/zram.sh ] && [ "$performance_improvements" == TRUE ] ;then
yad --center --width=410 --separator='\n' \
--title="Better Chromium" \
--window-icon="$(dirname "$0")/icon-64.png" \
--text="You've chosen to improve Chromium's performance by adding a few flags to it. Further improvement is possible by installing the More RAM app on Pi-Apps. This increases usable RAM while avoiding a swap file." \
--button="Thanks for the tip - I'll check out More RAM.":0 &>/dev/null &
elif [ ! -f /usr/bin/zram.sh ] && [ "$reduce_writes" == TRUE ] ;then
yad --center --width=410 --separator='\n' \
--title="Better Chromium" \
--window-icon="$(dirname "$0")/icon-64.png" \
--text="You've chosen to reduce writes to the SD card. Further improvement is possible by installing the More RAM app on Pi-Apps. This increases usable RAM while avoiding a swap file." \
--button="Thanks for the tip - I'll check out More RAM.":0 &>/dev/null &
fi
#
#write changes to chromium flag folder
#
status "Writing changes..."
#add zzzz_combine_values script in all cases to combine --enable-features arguments
echo "Creating workaround script at ${folder}/zzzz_combine_values"
cat << "EOF" | sudo tee "${folder}/zzzz_combine_values" >/dev/null
#This script combines multiple invocations of --enable-features and --disable-features into one argument so that Chromium does not ignore any.
#Written by Botspot for the Pi-Apps Better Chromium script.
IFS=' '
enable=''
disable=''
new_flags=''
for word in $CHROMIUM_FLAGS ;do
if [[ "$word" == '--enable-features='* ]];then
enable+=",${word/--enable-features=/}"
elif [[ "$word" == '--disable-features='* ]];then
enable+=",${word/--disable-features=/}"
else
new_flags+=" $word"
fi
done
#remove initial comma
enable="${enable/,/}"
disable="${disable/,/}"
CHROMIUM_FLAGS="$new_flags"
[ ! -z "$enable" ] && CHROMIUM_FLAGS+=" --enable-features=$enable"
[ ! -z "$disable" ] && CHROMIUM_FLAGS+=" --disable-features=$disable"
EOF
#dark mode
if [ "$dark_mode" == TRUE ];then
#I found this flag on https://peter.sh/experiments/chromium-command-line-switches
echo "Adding --force-dark-mode to ${folder}/dark_mode"
cat << EOF | sudo tee "${folder}/dark_mode" >/dev/null
export CHROMIUM_FLAGS="\$CHROMIUM_FLAGS --force-dark-mode"
EOF
else
#dark mode set to false - so remove the file
if [ -f "${folder}/dark_mode" ];then
status "Removing ${folder}/dark_mode"
fi
sudo rm -f "${folder}/dark_mode"
fi
#dark mode for all websites
if [ "$site_dark_mode" == TRUE ];then
#I found this flag on https://peter.sh/experiments/chromium-command-line-switches
echo "Adding --enable-features=WebContentsForceDark:inversion_method/cielab_based/image_behavior/none/foreground_lightness_threshold/150/background_lightness_threshold/150 to ${folder}/site_dark_mode"
cat << EOF | sudo tee "${folder}/site_dark_mode" >/dev/null
export CHROMIUM_FLAGS="\$CHROMIUM_FLAGS --enable-features=WebContentsForceDark:inversion_method/cielab_based/image_behavior/none/foreground_lightness_threshold/150/background_lightness_threshold/150" #WebContentsForceDark:increase_text_contrast/true"
EOF
else
#dark mode set to false - so remove the file
if [ -f "${folder}/site_dark_mode" ];then
status "Removing ${folder}/site_dark_mode"
fi
sudo rm -f "${folder}/site_dark_mode"
fi
#UI scale
if [ "$ui_scale" != 1.00 ];then
#I found this flag on https://peter.sh/experiments/chromium-command-line-switches
echo "Adding --device-scale-factor=${ui_scale} to ${folder}/ui_scale"
cat << EOF | sudo tee "${folder}/ui_scale" >/dev/null
export CHROMIUM_FLAGS="\$CHROMIUM_FLAGS --force-device-scale-factor=${ui_scale}"
EOF
else
#ui scale set to 1.00 (default), so remove file
if [ -f "${folder}/ui_scale" ];then
status "Removing ${folder}/ui_scale"
fi
sudo rm -f "${folder}/ui_scale"
fi
#Tab previews
if [ "$tab_previews" == TRUE ];then
#I found this flag after experimenting with chrome://flags and chrome://version
echo "Adding --enable-features=TabHoverCardImages to ${folder}/tab_previews"
cat << EOF | sudo tee "${folder}/tab_previews" >/dev/null
export CHROMIUM_FLAGS="\$CHROMIUM_FLAGS --enable-features=TabHoverCardImages"
EOF
else
#tab previews set to false - so remove the file
if [ -f "${folder}/tab_previews" ];then
status "Removing ${folder}/tab_previews"
fi
sudo rm -f "${folder}/tab_previews"
fi
#google_sync
if [ "$google_sync" == TRUE ];then
#add a file from official Debian version of the chromium package
echo "Adding GOOGLE_API_KEY, GOOGLE_DEFAULT_CLIENT_ID, and GOOGLE_DEFAULT_CLIENT_SECRET to ${folder}/apikeys"
cat << EOF | sudo tee "${folder}/apikeys" >/dev/null
# API keys found in chromium source code https://chromium.googlesource.com/experimental/chromium/src/+/b08bf82b0df37d15a822b478e23ce633616ed959/google_apis/google_api_keys.cc
export GOOGLE_API_KEY="AIzaSyCkfPOPZXDKNn8hhgu3JrA62wIgC93d44k"
export GOOGLE_DEFAULT_CLIENT_ID="77185425430.apps.googleusercontent.com"
export GOOGLE_DEFAULT_CLIENT_SECRET="OTJgUOQcT7lO7GsGZq2G4IlT"
EOF
echo "Adding ${folder}/enable_sync script to enable sync settings when Chromium launches"
cat << "EOF" | sudo tee "${folder}/enable_sync" >/dev/null
#!/bin/bash
profiles="$(find "$HOME/.config/chromium/" -maxdepth 1 -type d '(' -name Default -o -name 'Profile *' ')' | sed 's+.*/++g')"
IFS=$'\n'
for profile in $profiles ;do
[ ! -f "$HOME/.config/chromium/$profile/Preferences" ] && continue
sed -i 's/"signin":{"allowed":false}/"signin":{"allowed":true,"allowed_on_next_startup":true}/g' "$HOME/.config/chromium/$profile/Preferences"
sed -i 's/"signin":{"allowed":false,"allowed_on_next_startup":false}/"signin":{"allowed":true,"allowed_on_next_startup":true}/g' "$HOME/.config/chromium/$profile/Preferences"
sed -i 's/"signin":{"AccountReconcilor":{"kDiceMigrationOnStartup2":true},"allowed":false,"allowed_on_next_startup":false}/"signin":{"AccountReconcilor":{"kDiceMigrationOnStartup2":true},"allowed":true,"allowed_on_next_startup":true}/g' "$HOME/.config/chromium/$profile/Preferences"
done
EOF
else
#google sync set to false, so remove the file
if [ -f "${folder}/apikeys" ];then
status "Removing ${folder}/apikeys"
fi
#remove the script that enables sync setting
if [ -f "${folder}/enable_sync" ];then
status "Removing ${folder}/enable_sync"
fi
status "Disabling sync settings for all chromium profiles"
#turn off sync setting for every profile
profiles="$(find "$HOME/.config/chromium/" -maxdepth 1 -type d '(' -name Default -o -name 'Profile *' ')' | sed 's+.*/++g')"
IFS=$'\n'
for profile in $profiles ;do
[ ! -f "$HOME/.config/chromium/$profile/Preferences" ] && continue
sed -i 's/"signin":{"allowed":true}/"signin":{"allowed":false,"allowed_on_next_startup":false}/g' "$HOME/.config/chromium/$profile/Preferences"
sed -i 's/"signin":{"allowed":true,"allowed_on_next_startup":true}/"signin":{"allowed":false,"allowed_on_next_startup":false}/g' "$HOME/.config/chromium/$profile/Preferences"
sed -i 's/"signin":{"AccountReconcilor":{"kDiceMigrationOnStartup2":true},"allowed":true,"allowed_on_next_startup":true}/"signin":{"AccountReconcilor":{"kDiceMigrationOnStartup2":true},"allowed":false,"allowed_on_next_startup":false}/g' "$HOME/.config/chromium/$profile/Preferences"
done
sudo rm -f "${folder}/apikeys" "${folder}/enable_sync"
fi
#performance improvements
if [ "$performance_improvements" == TRUE ];then
#various chromium flags from https://forums.raspberrypi.com/viewtopic.php?t=199543 - I removed a few because they reduced stability or WebGL performance
#More flags added from https://www.ghacks.net/2017/02/13/how-to-speed-up-the-vivaldi-web-browser/
#Some VA-API flags from https://ubuntuhandbook.org/index.php/2022/07/chromium-snap-package-to-finally-get-back-vaapi-hardware-decoding/
flags="--ignore-gpu-blacklist --enable-checker-imaging --cc-scroll-animation-duration-in-seconds=0.6 --disable-quic --enable-tcp-fast-open --enable-experimental-canvas-features --enable-scroll-prediction --enable-simple-cache-backend --max-tiles-for-interest-area=512 --num-raster-threads=4 --default-tile-height=512 --enable-features=VaapiVideoDecoder,VaapiVideoEncoder --disable-features=UseChromeOSDirectVideoDecoder --enable-accelerated-video-decode --enable-low-res-tiling --process-per-site"
#The --process-per-site flag significantly decreases RAM usage and number of chromium processes, without any noticeable disadvantages.
#Not using --enable-low-end-device-mode even though it helps, because scrolling image-heavy pages would crash with "background allocation failure" error.
echo "Adding $flags to ${folder}/performance_improvements"
cat << EOF | sudo tee "${folder}/performance_improvements" >/dev/null
export CHROMIUM_FLAGS="\$CHROMIUM_FLAGS $flags"
EOF
else
#performance improvements set to false, so remove file
if [ -f "${folder}/performance_improvements" ];then
status "Removing ${folder}/performance_improvements"
fi
sudo rm -f "${folder}/performance_improvements"
fi
#reduce sd card writes
if [ "$reduce_writes" == TRUE ];then
#mount chromium files to tmpfs (script will run with user's privileges whenever Chromium is launched)
#From: https://forums.raspberrypi.com/viewtopic.php?p=1865820
echo "Adding ${folder}/reduce_writes script to mount cache/ServiceWorker to /dev/shm when Chromium launches"
cat << "EOF" | sudo tee "${folder}/reduce_writes" >/dev/null
#!/bin/bash
if [ ! -d /dev/shm ];then
echo 'Better chromium "Reduce Writes" script: cannot mount folders to /dev/shm because that folder is missing!'
else
rm -rf /dev/shm/chromium
mkdir -p /dev/shm/chromium
profiles="$(find "$HOME/.config/chromium/" -maxdepth 1 -type d '(' -name Default -o -name 'Profile *' ')' | sed 's+.*/++g')"
IFS=$'\n'
for profile in $profiles ;do
rm -rf "$HOME/.config/chromium/$profile/Service Worker"
mkdir -p "/dev/shm/chromium/$profile/serviceWorker"
ln -s "/dev/shm/chromium/$profile/serviceWorker" "$HOME/.config/chromium/$profile/Service Worker"
done
mkdir -p /dev/shm/chromium/cache
rm -rf "$HOME/.cache/chromium"
ln -s /dev/shm/chromium/cache/ "$HOME/.cache/chromium"
fi
EOF
else
if [ -f "${folder}/reduce_writes" ];then
status "Removing ${folder}/reduce_writes"
fi
sudo rm -f "${folder}/reduce_writes"
#clean up old symlinks
profiles="$(find "$HOME/.config/chromium/" -maxdepth 1 -type d '(' -name Default -o -name 'Profile *' ')' | sed 's+.*/++g')"
IFS=$'\n'
for profile in $profiles ;do
if [ -L "$HOME/.config/chromium/$profile/Service Worker" ];then
rm -rf "$HOME/.config/chromium/$profile/Service Worker"
fi
done
if [ -L "$HOME/.cache/chromium" ];then
rm -rf "$HOME/.cache/chromium"
fi
fi
#widevine
if [ "$widevine_possible" == TRUE ] && [ "$widevine" == TRUE ] && [ ! -d /opt/WidevineCdm ];then
#install Chromium Widevine app
"${DIRECTORY}/manage" install "Chromium Widevine"
elif [ "$widevine_possible" == TRUE ] && [ "$widevine" == FALSE ];then
#disable Chromium Widevine
if package_installed libwidevinecdm0 ;then
sudo apt purge -y libwidevinecdm0
fi
if [ -d /opt/WidevineCdm ];then
#uninstall Chromium Widevine app
"${DIRECTORY}/manage" uninstall "Chromium Widevine"
fi
fi
if pgrep chromium >/dev/null || pgrep chromium-browser >/dev/null ;then
status "Changes will take effect after you relaunch Chromium."
fi
true