#flags
file:///usr/local/bin/helium
set -- "${ARGS[@]}" "$@"
exec $CMD_PREFIX "$HERE/chrome" --enable-accelerated-2d-canvas --enable-accelerated-mjpeg-decode --enable-accelerated-video-decode --enable-fast-unload --enable-gpu-compositing --enable-gpu-rasterization --enable-native-gpu-memory-buffers --enable-zero-copy --enable-features=ParallelDownloading,VaapiVideoDecoder,VaapiVideoEncoder --use-gl=angle --use-angle=gl-egl --num-raster-threads=8 --process-per-site --ignore-gpu-blocklist --disable-overscroll-edge-effect --disable-features=UseChromeOSDirectVideoDecoder "$@"
#helium-install.sh
#!/bin/bash
set -euo pipefail
# ============================================================================
# Helium Browser Installer Script (Corrected & Upgraded)
#
# Target:
# - Debian 11 (Bullseye) on ARM64 (e.g., RK3588) or similar.
#
# Features:
# - Downloads Helium 0.6.9.1 ARM64 from GitHub.
# - Offers:
# * System-wide install: /opt/helium + /usr/local/bin/helium
# * Per-user install: $HOME/.local/helium + $HOME/.local/bin/helium
# - Installs dependencies via apt if missing.
# - Warns for potentially old glibc (< 2.32) and asks for confirmation.
# - Prefers chrome-wrapper (if present) over chrome as the launcher.
# - Integrates a desktop entry and updates desktop DB for system installs.
# - Asks for explicit confirmation before destructive operations.
# ============================================================================
HELIUM_VERSION="0.7.3.1"
HELIUM_ARCH="arm64"
GITHUB_REPO="imputnet/helium-linux"
DOWNLOAD_URL="https://github.com/${GITHUB_REPO}/releases/download/${HELIUM_VERSION}/helium-${HELIUM_VERSION}-${HELIUM_ARCH}_linux.tar.xz"
TARBALL_FILENAME="helium-${HELIUM_VERSION}-${HELIUM_ARCH}_linux.tar.xz"
DEFAULT_EXTRACTED_DIR_NAME="helium-${HELIUM_VERSION}-${HELIUM_ARCH}_linux"
SYSTEM_INSTALL_DIR="/opt/helium"
USER_INSTALL_DIR="${HOME}/.local/helium"
PRIMARY_BINARY_NAME="chrome"
WRAPPER_NAME="chrome-wrapper"
ICON_FILENAME="product_logo_256.png"
LAUNCHER_PATH=""
DESKTOP_FILE=""
TEMP_DIR=""
EXTRACTED_DIR_PATH=""
INSTALL_MODE="system"
REQUIRED_PACKAGES=(
wget
tar
xz-utils
desktop-file-utils
libgtk-3-0
libnss3
libasound2
libdbus-1-3
libx11-6
)
log() { echo "[*] $*"; }
warn() { echo "WARNING: $*" >&2; }
error_exit() { echo "Error: $*" >&2; exit 1; }
cleanup_temp_dir() {
if [ -n "${TEMP_DIR}" ] && [ -d "${TEMP_DIR}" ]; then
log "Cleaning up temporary directory: ${TEMP_DIR}"
rm -rf "${TEMP_DIR}"
fi
}
trap cleanup_temp_dir EXIT INT TERM
confirm_action() {
local message="$1"
echo
echo "==================================================================="
echo "CONFIRMATION REQUIRED:"
echo -e "${message}"
echo "==================================================================="
read -r -p "Type 'yes' to proceed, or anything else to cancel: " confirmation
if [[ "${confirmation}" != "yes" ]]; then
echo "Operation cancelled by user." >&2
return 1
fi
echo
return 0
}
ensure_command_available() {
local cmd="$1"
if ! command -v "${cmd}" >/dev/null 2>&1; then
error_exit "Required command '${cmd}' is not available in PATH. Please install it and re-run this script."
fi
}
ensure_package_installed() {
local pkg="$1"
if dpkg -s "${pkg}" >/dev/null 2>&1; then
log "Package '${pkg}' is already installed."
else
log "Installing package '${pkg}'..."
if ! sudo apt install -y "${pkg}"; then
error_exit "Failed to install package '${pkg}'."
fi
log "Package '${pkg}' installed successfully."
fi
}
check_apt_lock() {
if command -v fuser >/dev/null 2>&1; then
if fuser /var/lib/dpkg/lock >/dev/null 2>&1 || fuser /var/lib/apt/lists/lock >/dev/null 2>&1; then
warn "APT/dpkg appears to be locked. Another package manager process might be running."
warn "If you get lock errors, close other package tools and re-run this script."
fi
else
log "Skipping APT lock heuristic: 'fuser' is not available."
fi
}
check_environment() {
log "Checking system environment..."
local arch
arch="$(dpkg --print-architecture 2>/dev/null || echo "unknown")"
if [ "${arch}" != "arm64" ]; then
warn "This script is intended for ARM64 (arm64) systems, but detected '${arch}'."
else
log "Architecture: arm64 (OK)."
fi
if [ -r /etc/os-release ]; then
# shellcheck disable=SC1091
. /etc/os-release
local codename="${VERSION_CODENAME:-unknown}"
local pretty="${PRETTY_NAME:-Unknown}"
log "Detected OS: ${pretty} (codename: ${codename})"
if [ "${codename}" != "bullseye" ]; then
warn "Script is tuned for Debian 11 (Bullseye), but detected '${codename}'."
else
log "Debian 11 (Bullseye) detected (OK)."
fi
else
warn "Could not read /etc/os-release to detect OS version."
fi
log "Kernel: $(uname -r)"
log "Machine: $(uname -m)"
if [ -r /proc/cpuinfo ]; then
log "CPU model (first match in /proc/cpuinfo):"
grep -m 1 'model name' /proc/cpuinfo || true
fi
if [ "$(id -u)" -eq 0 ]; then
warn "You are running as root. Prefer running as a regular user with sudo."
fi
}
check_glibc_version() {
if ! command -v ldd >/dev/null 2>&1; then
warn "Cannot check glibc version (ldd not found); skipping glibc warning."
return
fi
log "Checking glibc version..."
local system_glibc_ver
system_glibc_ver="$(ldd --version | head -n1 | awk '{print $NF}')"
log "Detected glibc: ${system_glibc_ver}"
# Heuristic: warn if glibc appears older than 2.32 (a typical baseline for modern Chromium builds).
if [[ "$(printf '%s\n' '2.32' "${system_glibc_ver}" | sort -V | head -n1)" == "${system_glibc_ver}" && "${system_glibc_ver}" != "2.32" ]]; then
warn "glibc ${system_glibc_ver} is older than 2.32; Helium may fail to start."
if ! confirm_action "Continue installation despite potential glibc incompatibility?"; then
echo "Aborting due to glibc compatibility concern."
exit 0
fi
else
log "glibc version looks reasonably up-to-date."
fi
}
create_temp_dir() {
log "Creating temporary directory..."
TEMP_DIR="$(mktemp -d)"
if [ -z "${TEMP_DIR}" ] || [ ! -d "${TEMP_DIR}" ]; then
error_exit "Failed to create temporary directory."
fi
log "Using temporary directory: ${TEMP_DIR}"
}
download_tarball() {
log "Downloading Helium from: ${DOWNLOAD_URL}"
cd "${TEMP_DIR}" || error_exit "Failed to enter temporary directory."
if ! wget -O "${TARBALL_FILENAME}" "${DOWNLOAD_URL}"; then
error_exit "Failed to download Helium tarball."
fi
if [ ! -s "${TARBALL_FILENAME}" ]; then
error_exit "Downloaded tarball is empty or missing."
fi
local size
size="$(stat -c%s "${TARBALL_FILENAME}" 2>/dev/null || echo "unknown")"
log "Downloaded tarball (${size} bytes)."
}
verify_tarball() {
log "Verifying tarball integrity (tar -tf)..."
cd "${TEMP_DIR}" || error_exit "Failed to enter temporary directory."
if ! tar -tf "${TARBALL_FILENAME}" >/dev/null 2>&1; then
warn "tar -tf reported an error; the tarball may be corrupted. Extraction might fail."
else
log "Tarball looks valid."
fi
}
extract_tarball() {
log "Extracting tarball..."
cd "${TEMP_DIR}" || error_exit "Failed to enter temporary directory."
if ! tar -xf "${TARBALL_FILENAME}"; then
error_exit "Failed to extract tarball."
fi
if [ -d "${TEMP_DIR}/${DEFAULT_EXTRACTED_DIR_NAME}" ]; then
EXTRACTED_DIR_PATH="${TEMP_DIR}/${DEFAULT_EXTRACTED_DIR_NAME}"
log "Using expected extracted dir: ${EXTRACTED_DIR_PATH}"
else
local candidate
candidate="$(find "${TEMP_DIR}" -mindepth 1 -maxdepth 1 -type d | head -n1 || true)"
if [ -z "${candidate}" ]; then
error_exit "Could not determine extracted directory."
fi
EXTRACTED_DIR_PATH="${candidate}"
log "Using auto-detected extracted dir: ${EXTRACTED_DIR_PATH}"
fi
}
ask_install_mode() {
echo
echo "Installation mode:"
echo " 1) System-wide (/opt/helium, launcher /usr/local/bin/helium, needs sudo)"
echo " 2) Per-user (~/.local/helium, launcher ~/.local/bin/helium)"
echo
read -r -p "Choose mode [1/2, default: 1]: " choice
choice="${choice:-1}"
case "${choice}" in
1)
INSTALL_MODE="system"
LAUNCHER_PATH="/usr/local/bin/helium"
DESKTOP_FILE="/usr/share/applications/helium.desktop"
log "System-wide install selected."
;;
2)
INSTALL_MODE="user"
LAUNCHER_PATH="${HOME}/.local/bin/helium"
DESKTOP_FILE="${HOME}/.local/share/applications/helium.desktop"
log "Per-user install selected."
;;
*)
warn "Invalid choice '${choice}'. Defaulting to system-wide."
INSTALL_MODE="system"
LAUNCHER_PATH="/usr/local/bin/helium"
DESKTOP_FILE="/usr/share/applications/helium.desktop"
;;
esac
}
install_to_target() {
if [ -z "${EXTRACTED_DIR_PATH}" ]; then
error_exit "EXTRACTED_DIR_PATH is not set."
fi
local target_dir
if [ "${INSTALL_MODE}" = "system" ]; then
target_dir="${SYSTEM_INSTALL_DIR}"
if [ ! -d "/opt" ]; then
log "Creating /opt..."
if ! sudo mkdir -p /opt; then
error_exit "Failed to create /opt."
fi
fi
if sudo test -d "${target_dir}"; then
if ! confirm_action "Directory '${target_dir}' exists and will be deleted and replaced."; then
exit 1
fi
log "Removing old system-wide install at ${target_dir}..."
if ! sudo rm -rf "${target_dir}"; then
error_exit "Failed to remove old system install."
fi
fi
log "Installing to ${target_dir} (system-wide)..."
if ! sudo mv "${EXTRACTED_DIR_PATH}" "${target_dir}"; then
error_exit "Failed to move extracted directory into ${target_dir}."
fi
else
target_dir="${USER_INSTALL_DIR}"
if [ -d "${target_dir}" ]; then
if ! confirm_action "Directory '${target_dir}' exists and will be deleted and replaced."; then
exit 1
fi
log "Removing old per-user install at ${target_dir}..."
if ! rm -rf "${target_dir}"; then
error_exit "Failed to remove old user install."
fi
fi
local parent_dir
parent_dir="$(dirname "${target_dir}")"
if ! mkdir -p "${parent_dir}"; then
error_exit "Failed to create parent directory '${parent_dir}'."
fi
log "Installing to ${target_dir} (per-user)..."
if ! mv "${EXTRACTED_DIR_PATH}" "${target_dir}"; then
error_exit "Failed to move extracted directory into ${target_dir}."
fi
fi
log "Helium installed in ${target_dir}."
}
resolve_binary_path() {
local install_dir="$1"
local wrapper="${install_dir}/${WRAPPER_NAME}"
local binary="${install_dir}/${PRIMARY_BINARY_NAME}"
# Prefer chrome-wrapper if present; fall back to chrome.
if [ -x "${wrapper}" ]; then
echo "${wrapper}"
elif [ -x "${binary}" ]; then
echo "${binary}"
else
error_exit "Neither '${WRAPPER_NAME}' nor '${PRIMARY_BINARY_NAME}' found in '${install_dir}'."
fi
}
create_symlink_launcher() {
local install_dir
if [ "${INSTALL_MODE}" = "system" ]; then
install_dir="${SYSTEM_INSTALL_DIR}"
else
install_dir="${USER_INSTALL_DIR}"
fi
local target_binary
target_binary="$(resolve_binary_path "${install_dir}")"
if [ "${INSTALL_MODE}" = "user" ]; then
local launcher_dir
launcher_dir="$(dirname "${LAUNCHER_PATH}")"
if ! mkdir -p "${launcher_dir}"; then
error_exit "Failed to create launcher directory '${launcher_dir}'."
fi
fi
if [ -e "${LAUNCHER_PATH}" ] || [ -L "${LAUNCHER_PATH}" ]; then
if ! confirm_action "Launcher '${LAUNCHER_PATH}' exists and will be overwritten."; then
warn "Skipping launcher overwrite."
return
fi
fi
log "Creating launcher '${LAUNCHER_PATH}' -> '${target_binary}'..."
if [ "${INSTALL_MODE}" = "system" ]; then
if ! sudo ln -sf "${target_binary}" "${LAUNCHER_PATH}"; then
error_exit "Failed to create system launcher."
fi
else
if ! ln -sf "${target_binary}" "${LAUNCHER_PATH}"; then
error_exit "Failed to create user launcher."
fi
fi
log "Launcher created/updated."
}
create_desktop_entry() {
local install_dir
if [ "${INSTALL_MODE}" = "system" ]; then
install_dir="${SYSTEM_INSTALL_DIR}"
else
install_dir="${USER_INSTALL_DIR}"
fi
local icon_path="${install_dir}/${ICON_FILENAME}"
if [ ! -f "${icon_path}" ]; then
warn "Icon '${icon_path}' not found; desktop entry may show a generic icon."
fi
if [ "${INSTALL_MODE}" = "user" ]; then
local desktop_dir
desktop_dir="$(dirname "${DESKTOP_FILE}")"
if ! mkdir -p "${desktop_dir}"; then
error_exit "Failed to create desktop entry directory '${desktop_dir}'."
fi
fi
if [ -f "${DESKTOP_FILE}" ]; then
if ! confirm_action "Desktop file '${DESKTOP_FILE}' exists and will be overwritten."; then
warn "Skipping desktop entry overwrite."
return
fi
fi
log "Writing desktop entry to ${DESKTOP_FILE}..."
local icon_ref="${icon_path}"
if [ "${INSTALL_MODE}" = "system" ]; then
cat <<EOF | sudo tee "${DESKTOP_FILE}" >/dev/null
[Desktop Entry]
Version=1.0
Name=Helium Browser
GenericName=Web Browser
Comment=Private, fast, and honest web browser
Exec=${LAUNCHER_PATH} %U
TryExec=${LAUNCHER_PATH}
Icon=${icon_ref}
StartupNotify=false
StartupWMClass=helium
Terminal=false
Type=Application
Categories=Network;WebBrowser;
MimeType=application/pdf;application/rdf+xml;application/rss+xml;application/xhtml+xml;application/xhtml_xml;application/xml;image/gif;image/jpeg;image/png;image/webp;text/html;text/xml;x-scheme-handler/http;x-scheme-handler/https;
Actions=new-window;new-private-window;
[Desktop Action new-window]
Name=New Window
Exec=${LAUNCHER_PATH} %U
TryExec=${LAUNCHER_PATH}
Icon=${icon_ref}
[Desktop Action new-private-window]
Name=New Private Window
Exec=${LAUNCHER_PATH} --incognito %U
TryExec=${LAUNCHER_PATH}
Icon=${icon_ref}
EOF
else
cat <<EOF > "${DESKTOP_FILE}"
[Desktop Entry]
Version=1.0
Name=Helium Browser
GenericName=Web Browser
Comment=Private, fast, and honest web browser
Exec=${LAUNCHER_PATH} %U
TryExec=${LAUNCHER_PATH}
Icon=${icon_ref}
StartupNotify=false
StartupWMClass=helium
Terminal=false
Type=Application
Categories=Network;WebBrowser;
MimeType=application/pdf;application/rdf+xml;application/rss+xml;application/xhtml+xml;application/xhtml_xml;application/xml;image/gif;image/jpeg;image/png;image/webp;text/html;text/xml;x-scheme-handler/http;x-scheme-handler/https;
Actions=new-window;new-private-window;
[Desktop Action new-window]
Name=New Window
Exec=${LAUNCHER_PATH} %U
TryExec=${LAUNCHER_PATH}
Icon=${icon_ref}
[Desktop Action new-private-window]
Name=New Private Window
Exec=${LAUNCHER_PATH} --incognito %U
TryExec=${LAUNCHER_PATH}
Icon=${icon_ref}
EOF
fi
log "Desktop entry created/updated."
}
update_desktop_database_safe() {
log "Updating system desktop database (if available)..."
if command -v update-desktop-database >/dev/null 2>&1; then
if ! sudo update-desktop-database >/dev/null 2>&1; then
warn "update-desktop-database reported an error; you may still need to log out/in."
else
log "Desktop database updated."
fi
else
warn "update-desktop-database not found; rely on desktop environment’s automatic refresh."
fi
}
print_troubleshooting_tips() {
echo
echo "Troubleshooting tips:"
echo " - To check for missing libraries:"
echo " ldd \"\$(command -v helium)\" | grep 'not found'"
echo " - For GLIBC errors (GLIBC_2.xx not found):"
echo " your system glibc is older than required; consider OS upgrade or using a different build."
echo " - For GPU issues on RK3588:"
echo " helium --use-gl=egl"
echo " helium --disable-gpu"
echo " - If Helium doesn’t appear in menu:"
echo " check desktop file at: ${DESKTOP_FILE}"
echo " log out/in or, for system install, run: sudo update-desktop-database"
echo
}
print_summary() {
echo
echo "==================================================================="
echo "Helium installation complete."
echo "==================================================================="
echo "Mode : ${INSTALL_MODE}"
if [ "${INSTALL_MODE}" = "system" ]; then
echo "Install dir : ${SYSTEM_INSTALL_DIR}"
else
echo "Install dir : ${USER_INSTALL_DIR}"
fi
echo "Launcher : ${LAUNCHER_PATH}"
echo "Desktop entry : ${DESKTOP_FILE}"
echo
echo "Run Helium with: helium"
echo "Or via your desktop's application menu (Helium Browser)."
echo "==================================================================="
}
main() {
log "Helium Browser Installer starting..."
# We assume 'sudo' is present; other tools are installed via apt as needed.
ensure_command_available "sudo"
check_environment
check_glibc_version
check_apt_lock
log "Updating APT package index..."
if ! sudo apt update; then
error_exit "APT update failed."
fi
log "Ensuring required packages are installed..."
local pkg
for pkg in "${REQUIRED_PACKAGES[@]}"; do
ensure_package_installed "${pkg}"
done
log "Dependencies satisfied."
ask_install_mode
create_temp_dir
download_tarball
verify_tarball
extract_tarball
install_to_target
create_symlink_launcher
create_desktop_entry
if [ "${INSTALL_MODE}" = "system" ]; then
update_desktop_database_safe
else
log "Per-user install: system desktop DB update is not required."
fi
print_troubleshooting_tips
print_summary
}
main "$@"