The Copy URL extension was intermittently failing to copy anything, and
its notification looked oversized with no icon. Several distinct problems:
- The MV3 service worker was pinned to stale cached code. Chromium caches
the worker script for a --load-extension command-line extension and does
NOT re-register it when the file changes in place — not on restart, not on
a manifest version bump, not even after a clean shutdown. So updated code
never took effect: the old worker kept calling chrome.scripting.executeScript,
which throws once the scripting permission is gone, and the copy silently
failed. Renaming the worker to a versioned filename (background-2.js) is a
new script URL, which forces a fresh registration for everyone — new
installs and existing installs alike. Rename it again on any future worker
change (see the note at the top of background-2.js).
- Clipboard writes now go through an offscreen document (MV3's sanctioned
path) using a textarea + execCommand('copy'), replacing executeScript +
navigator.clipboard. This works on chrome:// pages and needs no scripting
permission. execCommand is used deliberately: navigator.clipboard.writeText
rejects in an unfocused offscreen document.
- Add a toolbar action (chrome.action.onClicked) so the extension is
clickable, not keyboard-only — it was greyed out in the extensions menu
with nothing to invoke.
- Slim the "URL copied" notification: lead the summary with a glyph so the
omarchy notification shell collapses it to a single-line toast with an
icon, instead of an oversized card with a blank icon slot.
- Guard the Quattro shortcut-repair migration: it edits Chromium Preferences
to move the Alt+Shift+L binding to the new extension id, but a running
browser rewrites Preferences on exit and reverts the edit. Prompt (via gum)
to close the browser first, only when a browser is running and there is
actually a stale binding to repair.
89 lines
4.1 KiB
Bash
89 lines
4.1 KiB
Bash
#!/bin/bash
|
|
|
|
source "$(dirname "${BASH_SOURCE[0]}")/base-test.sh"
|
|
|
|
export PATH="$ROOT/bin:$PATH"
|
|
|
|
TMPDIR=""
|
|
|
|
cleanup() {
|
|
[[ -n $TMPDIR && -d $TMPDIR ]] && rm -rf "$TMPDIR"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
require_command jq
|
|
require_command node
|
|
|
|
copy_url_id=$(node - <<'JS' "$ROOT/default/chromium/extensions/copy-url/manifest.json"
|
|
const crypto = require('crypto')
|
|
const fs = require('fs')
|
|
|
|
const manifest = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'))
|
|
const hash = crypto.createHash('sha256').update(Buffer.from(manifest.key, 'base64')).digest()
|
|
const alphabet = 'abcdefghijklmnop'
|
|
let id = ''
|
|
|
|
for (const byte of hash.subarray(0, 16)) {
|
|
id += alphabet[byte >> 4]
|
|
id += alphabet[byte & 0x0f]
|
|
}
|
|
|
|
process.stdout.write(id)
|
|
JS
|
|
)
|
|
|
|
[[ $copy_url_id == "bgpiichlckmfanooecilcjemknkcpngb" ]] ||
|
|
fail "copy-url extension manifest has the stable id" "$copy_url_id"
|
|
pass "copy-url extension manifest has the stable id"
|
|
|
|
jq -e '
|
|
.manifest_version == 3 and
|
|
(.permissions | index("clipboardWrite")) and
|
|
(.permissions | index("offscreen")) and
|
|
(.background.service_worker | startswith("background-"))
|
|
' "$ROOT/default/chromium/extensions/copy-url/manifest.json" >/dev/null ||
|
|
fail "copy-url extension uses an offscreen clipboard document"
|
|
[[ -f $ROOT/default/chromium/extensions/copy-url/offscreen.html &&
|
|
-f $ROOT/default/chromium/extensions/copy-url/offscreen.js ]] ||
|
|
fail "copy-url extension ships its offscreen clipboard document"
|
|
pass "copy-url extension uses an offscreen clipboard document"
|
|
|
|
jq -e '.action != null' "$ROOT/default/chromium/extensions/copy-url/manifest.json" >/dev/null &&
|
|
grep -q 'action.onClicked' "$ROOT/default/chromium/extensions/copy-url/"background-*.js ||
|
|
fail "copy-url extension is clickable from the toolbar"
|
|
pass "copy-url extension is clickable from the toolbar"
|
|
|
|
TMPDIR=$(mktemp -d)
|
|
preferences="$TMPDIR/Preferences"
|
|
backup="$TMPDIR/Preferences.bak"
|
|
patch_script="$TMPDIR/repair-shortcuts.py"
|
|
|
|
awk '
|
|
/<<'\''CHROMIUM_SHORTCUTS_PATCH_PY'\''/ { copying = 1; next }
|
|
copying && $0 == "CHROMIUM_SHORTCUTS_PATCH_PY" { exit }
|
|
copying { print }
|
|
' "$ROOT/bin/omarchy-upgrade-to-quattro" >"$patch_script"
|
|
|
|
cat >"$preferences" <<'JSON'
|
|
{"extensions":{"commands":{"linux:Alt+Shift+L":{"command_name":"copy-url","extension":"bocglpkldciamkbmlphanhkfnhpmnbma","global":false},"linux:Alt+Shift+D":{"command_name":"download-video","extension":"dedjgknigfeelejglamclffonmophnfl","global":false}},"settings":{"bocglpkldciamkbmlphanhkfnhpmnbma":{"commands":{"copy-url":{"suggested_key":"Alt+Shift+L","was_assigned":true}}},"bgpiichlckmfanooecilcjemknkcpngb":{"commands":{"copy-url":{"suggested_key":"Alt+Shift+L"}}}}}}
|
|
JSON
|
|
|
|
python3 "$patch_script" "$preferences" "$backup"
|
|
|
|
jq -e '
|
|
.extensions.commands["linux:Alt+Shift+L"].extension == "bgpiichlckmfanooecilcjemknkcpngb" and
|
|
.extensions.commands["linux:Alt+Shift+D"].extension == "dedjgknigfeelejglamclffonmophnfl" and
|
|
(.extensions.settings.bocglpkldciamkbmlphanhkfnhpmnbma.commands["copy-url"] | has("was_assigned") | not) and
|
|
.extensions.settings.bgpiichlckmfanooecilcjemknkcpngb.commands["copy-url"].was_assigned == true
|
|
' "$preferences" >/dev/null || fail "quattro upgrade moves the Copy URL shortcut to the stable extension id"
|
|
cmp -s "$backup" <(printf '%s\n' '{"extensions":{"commands":{"linux:Alt+Shift+L":{"command_name":"copy-url","extension":"bocglpkldciamkbmlphanhkfnhpmnbma","global":false},"linux:Alt+Shift+D":{"command_name":"download-video","extension":"dedjgknigfeelejglamclffonmophnfl","global":false}},"settings":{"bocglpkldciamkbmlphanhkfnhpmnbma":{"commands":{"copy-url":{"suggested_key":"Alt+Shift+L","was_assigned":true}}},"bgpiichlckmfanooecilcjemknkcpngb":{"commands":{"copy-url":{"suggested_key":"Alt+Shift+L"}}}}}}') ||
|
|
fail "quattro upgrade backs up Chromium preferences before shortcut repair"
|
|
pass "quattro upgrade repairs and backs up the Copy URL shortcut"
|
|
|
|
unchanged_hash=$(sha256sum "$preferences" | cut -d' ' -f1)
|
|
rm "$backup"
|
|
python3 "$patch_script" "$preferences" "$backup"
|
|
[[ $(sha256sum "$preferences" | cut -d' ' -f1) == "$unchanged_hash" && ! -e $backup ]] ||
|
|
fail "Copy URL shortcut repair is idempotent"
|
|
pass "Copy URL shortcut repair is idempotent"
|