From 06dee246c994132aaf6813db91dfdd2bc5bd215e Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 17 May 2026 15:46:25 +0200 Subject: [PATCH] =?UTF-8?q?feat(01-09):=20GREEN=20=E2=80=94=20toolbar=20on?= =?UTF-8?q?Clicked=20+=20badge=20state=20machine=20+=20onStartup=20notific?= =?UTF-8?q?ation=20+=20SAVE-only=20popup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plan 01-09 Task 4 GREEN — flips all 13 Task 3 RED tests to GREEN: src/background/index.ts: • Badge palette + notification id prefix constants (SCREAMING_SNAKE). • setBadgeState(state) helper: 3-state machine REC/OFF/ERROR with deterministic setBadgeText + setBadgeBackgroundColor + setTitle. Each chrome call wrapped in try/catch (defense in depth). • setIdleMode / setRecordingMode / setErrorMode helpers — drive the setPopup dance: '' in OFF (so onClicked fires), html path in REC/ ERROR (so popup opens for SAVE). • startVideoCapture wires setRecordingMode on success, setErrorMode in catch. • chrome.action.onClicked.addListener — direct toolbar-to-picker flow (no popup needed for start). isRecording guard prevents double-start. • chrome.runtime.onStartup.addListener — fires once per browser session; creates mokosh-startup- notification inviting recording. • chrome.notifications.onClicked.addListener — T-1-09-01 spoofing mitigation via 'mokosh-' prefix gate; clears notification + invokes startVideoCapture (notification click is a valid activation gesture). • RECORDING_ERROR onMessage branch — setErrorMode + creates a mokosh-recovery- notification inviting the operator to restart. • initialize() calls setIdleMode at SW boot — ensures fresh OFF state on every (re-)spawn including Chrome's idle-eviction respawn. • All new listener registrations wrapped in try/catch so unit-test chrome stubs that don't define action/notifications/onStartup don't crash SW load (preserves the 5 pre-existing request-id-protocol + 1 port-lifecycle-continuous tests as GREEN). src/popup/index.ts: • Removed checkPermissions + requestPermissions functions entirely (no more REQUEST_PERMISSIONS round-trip on popup open). • popupState defaults isRecording=true, hasPermissions=true under SAVE-only charter — the popup ONLY opens when recording is active (REC/ERROR setPopup html path), so SAVE button is always enabled. • init() calls updateUI() directly (no async permission probe). • Empty-state copy updated: 'Откройте запись через иконку расширения' (Open recording via the extension icon — points operator back to the toolbar for starting a new session). • saveArchive() simplified: no permission re-check. manifest.json: • Added 'notifications' to permissions array (preserves all existing). • default_popup retained — popup still opens in REC/ERROR modes. smoke.sh (W-04 5-sub-step update): • SHARE_TARGET='Entire screen' (was 'Mokosh Smoke Test'). • Added 14-line locale-fallback comment block citing Chromium generated_resources.grd as authoritative source + 4 known locale strings + KEEP_PROFILE=1 fallback path. • changed to 'Mokosh Smoke Test — monitor mode' to keep tab title distinct from the screen-source string. • <ol> instruction updated: picker auto-accepts entire screen, not the tab. Body intro paragraph also updated. • T+/wall timer overlay (commit 923aaca) preserved — no behavioral change to polling/Downloads-snapshot/ffprobe-gate logic. Tests: 13/13 new GREEN; full suite 18 files / 81 tests / all GREEN. tsc --noEmit exit 0. npm run build exit 0; dist/manifest.json has 'notifications' permission. Tier-1 SW-bundle-import gate (Layer 1 + 2) remains GREEN. --- manifest.json | 3 +- smoke.sh | 26 +++++- src/background/index.ts | 171 ++++++++++++++++++++++++++++++++++++++++ src/popup/index.ts | 89 ++++++--------------- 4 files changed, 219 insertions(+), 70 deletions(-) diff --git a/manifest.json b/manifest.json index 25b2ed0..5fa1a21 100644 --- a/manifest.json +++ b/manifest.json @@ -9,7 +9,8 @@ "downloads", "scripting", "storage", - "offscreen" + "offscreen", + "notifications" ], "host_permissions": [ "<all_urls>" diff --git a/smoke.sh b/smoke.sh index c582d4c..0f5e2d1 100755 --- a/smoke.sh +++ b/smoke.sh @@ -41,7 +41,25 @@ DOWNLOADS_DIR="${HOME}/Downloads" FIXTURE_DEST="${REPO_DIR}/tests/fixtures/last_30sec.webm" WEBM_TMP="/tmp/mokosh-last_30sec.webm" CHROME_LOG="/tmp/mokosh-chrome.log" -SHARE_TARGET="Mokosh Smoke Test" +# Plan 01-09 D-15-display-surface: SHARE_TARGET must match the OS-locale- +# specific name Chrome's picker uses for entire-screen selection. Known +# strings (Chrome stable, observed at plan-write time): +# English: "Entire screen" +# Russian: "Весь экран" +# German: "Gesamter Bildschirm" +# French: "Ecran entier" +# Authoritative source: Chromium's grit resource definitions in +# chrome/app/generated_resources.grd (per-locale .xtb translations under +# chrome/app/resources/). The IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_SCREEN +# identifier lives in the .grd, NOT in the .cc — per-locale translations +# drift across Chrome major versions, so the only reliable check is to +# run the picker once and inspect the source label in Chrome's UI. +# If --auto-select-desktop-capture-source="${SHARE_TARGET}" fails to +# auto-accept on the operator's Chrome locale, the operator picks the +# screen manually one time; KEEP_PROFILE=1 on subsequent runs carries +# the picker's last-pick memory across re-runs, sidestepping the +# auto-select string altogether. +SHARE_TARGET="Entire screen" CHROME_BIN="${CHROME_BIN:-/usr/bin/google-chrome-stable}" KEEP_PROFILE="${KEEP_PROFILE:-0}" POLL_TIMEOUT="${POLL_TIMEOUT:-900}" @@ -104,7 +122,7 @@ fi # --- compose the smoke tab data URL --- read -r -d '' SMOKE_HTML <<'EOF' || true -<title>Mokosh Smoke Test +Mokosh Smoke Test — monitor mode