Free the Copy URL shortcut from ghost extension registrations (#6821)

* Rebind ghost Copy URL shortcut registrations to the pinned id

Chromium never hands a suggested shortcut to one extension while
another — even a long-gone one — still holds the registration. Profiles
that first loaded Copy URL before its id was pinned registered
Alt+Shift+L under an id derived from the extension's load path at the
time, so the pinned extension never receives the shortcut and the
keypress does nothing (#6816).

The quattro upgrade tried to repair this against one hardcoded
path-derived id, which only ever matched a single home directory. The
historical ids are unknowable in general — they hash long-gone absolute
paths through whatever symlinks existed then — but the registration
itself names the command, so a migration now rebinds any copy-url
command that points away from the pinned id, unless that id belongs to
an extension that is actually installed or the pinned extension already
holds a binding of its own.

Browsers rewrite Preferences on exit, which reverts any repair made
while one runs, so the migration asks for this user's browser windows to
be closed first — failing and staying pending when there is no terminal
to ask in or the prompt is declined. The backup a repair leaves behind
marks it as attempted but unverified: until a browser-free run confirms
the registration stayed repaired, the migration keeps itself pending
rather than trusting a disk state an open browser may still overwrite.

The upgrade-time repair is dropped: the upgrade already runs migrations,
so the migration is the single implementation.

Fixes #6816

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Pin the WhatsApp Slim extension id

Keyless unpacked extensions get path-derived ids, which go stale if the
load path or packaging ever changes — the same class of bug that broke
the Copy URL shortcut for pre-package installs. Pin the id with a
manifest key like the other bundled extensions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
David Heinemeier Hansson
2026-08-13 22:37:29 +02:00
committed by GitHub
co-authored by Claude Fable 5
parent 30f8f191c0
commit de854d3f0c
6 changed files with 399 additions and 113 deletions
-77
View File
@@ -1792,82 +1792,6 @@ CHROMIUM_FLAGS_PATCH_PY
done
}
# True if any Chromium-family browser that stores the Copy URL shortcut is running.
browser_is_running() {
pgrep -x 'chromium|chrome|brave|msedge|vivaldi-bin|vivaldi|opera|helium' >/dev/null 2>&1
}
repair_chromium_copy_url_shortcuts() {
local profile_root preferences
local -a profile_roots=(
"$HOME/.config/chromium"
"$HOME/.config/google-chrome"
"$HOME/.config/google-chrome-beta"
"$HOME/.config/BraveSoftware/Brave-Browser"
"$HOME/.config/BraveSoftware/Brave-Browser-Beta"
"$HOME/.config/microsoft-edge"
"$HOME/.config/microsoft-edge-beta"
"$HOME/.config/vivaldi"
"$HOME/.config/opera"
"$HOME/.config/helium"
)
local -a pending=()
for profile_root in "${profile_roots[@]}"; do
[[ -d $profile_root ]] || continue
for preferences in "$profile_root"/*/Preferences; do
[[ -f $preferences ]] || continue
grep -qF 'bocglpkldciamkbmlphanhkfnhpmnbma' "$preferences" || continue
pending+=("$preferences")
done
done
(( ${#pending[@]} )) || return 0
# A running browser holds Preferences in memory and rewrites it on exit,
# which would revert this repair. Ask the user to close it first.
if browser_is_running && (( ! OMARCHY_UPGRADE_YES )) && [[ -r /dev/tty ]]; then
if ! gum confirm "Close all browser windows before the Copy URL shortcut is repaired, then continue" </dev/tty; then
echo "Skipped Copy URL shortcut repair; re-run after closing your browser." >&2
return 0
fi
fi
for preferences in "${pending[@]}"; do
python3 - "$preferences" "$preferences.omarchy-upgrade-to-quattro.$BACKUP_SUFFIX.bak" <<'CHROMIUM_SHORTCUTS_PATCH_PY'
import json
import shutil
import sys
from pathlib import Path
path = Path(sys.argv[1])
backup_path = Path(sys.argv[2])
old_id = "bocglpkldciamkbmlphanhkfnhpmnbma"
new_id = "bgpiichlckmfanooecilcjemknkcpngb"
preferences = json.loads(path.read_text())
extensions = preferences.get("extensions", {})
commands = extensions.get("commands", {})
changed = False
for command in commands.values():
if command.get("extension") == old_id and command.get("command_name") == "copy-url":
command["extension"] = new_id
changed = True
if changed:
settings = extensions.get("settings", {})
old_command = settings.get(old_id, {}).get("commands", {}).get("copy-url", {})
new_command = settings.get(new_id, {}).get("commands", {}).get("copy-url", {})
old_command.pop("was_assigned", None)
if new_command:
new_command["was_assigned"] = True
shutil.copy2(path, backup_path)
path.write_text(json.dumps(preferences, separators=(",", ":")))
CHROMIUM_SHORTCUTS_PATCH_PY
done
}
repair_sleep_lock_unit_override() {
local unit="$HOME/.config/systemd/user/omarchy-sleep-lock.service"
local legacy_exec='ExecStart=%h/.local/share/omarchy/bin/omarchy-system-sleep-monitor'
@@ -1964,7 +1888,6 @@ copy_missing_config_defaults "$root/config" "$HOME/.config"
mark_removed_preinstalls_from_legacy_bindings
copy_always_config_defaults
repair_chromium_copy_url_extension_flags
repair_chromium_copy_url_shortcuts
# Carry over user-added backgrounds from the legacy git checkout backup, then
# remove old symlinks that pointed ~/.config/omarchy/themes/* back into the