* Speed up theme switch by backgrounding preload and parallelizing browser refresh `omarchy theme set` was blocking on `omarchy-theme-switcher --preload` (~1.1s) and serially refreshing every Chromium-family browser (~1.0-1.5s), making a picked theme feel slow even though the shell recolored instantly. - Background `omarchy-theme-switcher --preload` like the background cache - In `omarchy-theme-set-browser`, skip the privileged policy write and browser refreshes when every existing `color.json` already has the requested color - Refresh only running browsers, and run those refreshes in parallel Fixes #12627. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * Harden the unchanged-color shortcut in omarchy-theme-set-browser Review feedback identified that the original shortcut could vacuously skip when no managed policy directories existed, and that it accepted a color.json whose ownership or contents the privileged writer would have rewritten. - Only skip when at least one managed directory exists and every existing color.json is a regular, root-owned 0644 file containing the canonical JSON - Add OMARCHY_BROWSER_POLICY_DIRS as a test-only override so the setter's unchanged-color check does not depend on the host's real /etc policy files - Update browser-policy-sudoers-test.sh to use that override, and make theme-set-browser-test.sh behavioral rather than grep-only Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * Find running browsers with one process scan during the policy write Each browser check ran its own pgrep, and every pgrep rescans /proc, ~40ms apiece. Read the process table once with ps while the policy writer runs, keeping its stdin so a terminal sudo prompt stays in the terminal, then refresh the running browsers in parallel. Chrome's fallback to plain google-chrome never ran: the refresh helper returned success for a missing browser, so the || branch was dead. Pick whichever Chrome binary exists up front instead. The unchanged-color shortcut keeps its root:root 0644 check without the fallback for hosts lacking stat -c, which Omarchy never runs on. Its tests stub stat, ps and command discovery, so they neither depend on nor touch the host's browsers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: David Heinemeier Hansson <david@hey.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
95 lines
3.2 KiB
Bash
Executable File
95 lines
3.2 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# omarchy:summary=Apply the current theme color to Chromium, Chrome, Edge, and Brave
|
|
# omarchy:hidden=true
|
|
|
|
source "$OMARCHY_PATH/install/helpers/browser-policy.sh"
|
|
|
|
CHROMIUM_THEME=$HOME/.local/state/omarchy/current/theme/chromium.theme
|
|
THEME_HEX_COLOR=$BROWSER_POLICY_DEFAULT_COLOR
|
|
|
|
if [[ -f $CHROMIUM_THEME ]]; then
|
|
THEME_HEX_COLOR=$(browser_policy_theme_hex "$(<$CHROMIUM_THEME)")
|
|
fi
|
|
|
|
# Tests override this with a temporary directory list; production uses the
|
|
# fixed trust-root set from browser-policy.sh.
|
|
POLICY_DIRS=("${BROWSER_POLICY_MANAGED_DIRS[@]}")
|
|
if [[ -n ${OMARCHY_BROWSER_POLICY_DIRS:-} ]]; then
|
|
POLICY_DIRS=()
|
|
while IFS= read -r dir; do
|
|
POLICY_DIRS+=("$dir")
|
|
done <<< "$OMARCHY_BROWSER_POLICY_DIRS"
|
|
fi
|
|
|
|
# A managed color.json is already correct only when it is a regular, root-owned
|
|
# file with mode 0644 containing exactly the canonical JSON for the requested
|
|
# color.
|
|
file_is_canonical() {
|
|
local file=$1
|
|
[[ -f $file && ! -L $file ]] || return 1
|
|
[[ $(<"$file") == "$expected_json" ]] || return 1
|
|
[[ $(stat -c '%U:%G %a' "$file") == "root:root 644" ]]
|
|
}
|
|
|
|
# Skip the privileged policy write and browser refreshes entirely when every
|
|
# existing managed color.json is already canonical. The writer only touches
|
|
# directories that exist, so a browser installed since then has no color.json
|
|
# yet and takes the write.
|
|
expected_json='{"BrowserThemeColor": "'$THEME_HEX_COLOR'", "BrowserColorScheme": "device"}'
|
|
saw_any=false
|
|
all_unchanged=true
|
|
for dir in "${POLICY_DIRS[@]}"; do
|
|
[[ -d $dir && ! -L $dir ]] || continue
|
|
saw_any=true
|
|
|
|
if ! file_is_canonical "$dir/color.json"; then
|
|
all_unchanged=false
|
|
break
|
|
fi
|
|
done
|
|
$saw_any && $all_unchanged && exit 0
|
|
|
|
failed=0
|
|
# A script's background job reads /dev/null unless told otherwise, which would
|
|
# turn the writer's terminal sudo prompt into a pkexec dialog. Keep stdin.
|
|
omarchy-theme-set-browser-policy "${THEME_HEX_COLOR#\#}" <&0 &
|
|
policy_pid=$!
|
|
|
|
# While the policy writes, find the running browsers with one process table
|
|
# read. A pgrep per browser rescans /proc each time, ~40ms apiece.
|
|
declare -A running_names=()
|
|
running_args=""
|
|
while read -r name args; do
|
|
running_names[$name]=1
|
|
running_args+="$args"$'\n'
|
|
done < <(ps -eo comm=,args=)
|
|
|
|
# Chrome installs as either binary name, so take whichever exists.
|
|
chrome=google-chrome-stable
|
|
omarchy-cmd-present "$chrome" || chrome=google-chrome
|
|
|
|
browsers_to_refresh=()
|
|
for browser in chromium:chromium "chrome:$chrome" msedge:microsoft-edge-stable brave:brave; do
|
|
[[ -n ${running_names[${browser%%:*}]:-} ]] && omarchy-cmd-present "${browser#*:}" && browsers_to_refresh+=("${browser#*:}")
|
|
done
|
|
# Match on the binary path: the running process is named plain "brave", and a
|
|
# bare brave-origin pattern would also match the installer's own terminal.
|
|
[[ $running_args == *"/opt/brave-origin-bin/"* ]] && omarchy-cmd-present brave-origin && browsers_to_refresh+=(brave-origin)
|
|
|
|
wait "$policy_pid" || failed=1
|
|
|
|
# Refresh each running browser in parallel, so one slow launch doesn't
|
|
# serialize the rest.
|
|
refresh_pids=()
|
|
for command in "${browsers_to_refresh[@]}"; do
|
|
"$command" --refresh-platform-policy --no-startup-window &>/dev/null &
|
|
refresh_pids+=("$!")
|
|
done
|
|
|
|
for pid in "${refresh_pids[@]}"; do
|
|
wait "$pid"
|
|
done
|
|
|
|
exit "$failed"
|