v1.3.4
Small quality update from a full audit pass: bug fixes, polish, accessibility, and one minor code-quality cleanup. No new permissions, no new strings, no schema changes.
Fixed
- Startup suspend pass could be skipped when the service worker died before the 5s timer fired.
onStartupscheduledsuspendAllOnStartupviasetTimeout(..., 5000). OnceonStartup's awaits resolve, the service worker has no pending events keeping it alive; Chrome can terminate it after ~30s of idle, and a setTimeout doesn't count as keepalive. On a cold browser launch where the worker has no other work, the 5s deadline was usually hit, but not guaranteed. Replaced withchrome.alarms.create('startup-suspend', { delayInMinutes: 0.1 })which Chrome clamps to ~30s in production and survives a worker restart. TheonAlarmhandler now dispatches thestartup-suspendalarm tosuspendAllOnStartup(after re-fetching settings, in case the user toggled "Suspend on startup" off between the schedule and the fire). handleSuspendCurrentfell back tocandidates[length - 1]when no next tab existed, which could land far from the active tab (the last candidate in the filtered list, not necessarily the previous tab). Now it explicitly looks for the closest previous tab (largestindexbelowactiveTab.index), then falls back to any candidate only if both next and previous are absent. Triggered when you suspend the active tab viaAlt+S/ context menu while it's the rightmost tab in a window.
Changed
MB_PER_TABis now defined once per file rather than scattered as a magic150in three places inpopup.js. The constant must stay in sync withbackground.js'sMB_PER_TAB; comment inpopup.jscalls this out. No user-visible change; defensive cleanup so a future tuning is a one-line edit.
Polish
prefers-reduced-motionhonored on the onboarding page. The popup, side panel, changelog, and privacy-policy pages all already had the media query that flattens animations and transitions to 1ms;onboarding.htmlwas the only page that didn't, so a user with reduced-motion enabled would still see the 0.4s fade-up of the welcome container. Added the same* { animation-duration: 1ms !important; ... }block toonboarding.html's inline style.- Whitelist input HTML placeholder synced with the i18n value. The 1.3.3 release updated
en/messages.json#whitelistPlaceholderto"example.com, full URL, or site.com/path/*"but the staticplaceholder=attribute inpopup.htmlandsidepanel.htmlwas still"example.com or site.com/path/*". Localization overwrites it at popup-open, so users normally see the new wording, but a failed i18n pass (extension reload race, unusual locale) would leave the old text visible. HTML defaults now match en exactly.
Audit
- Full read-through of all source files.
background.js,popup.js/html/css,sidepanel.html,formcheck.js,icons.js,onboarding.html/js,changelog.html/js,privacy-policy.html/js. No additional bugs found beyond the two fixed above; the 1.3.2 / 1.3.3 polish work held up. - All 57 locale files validated for JSON validity, key parity against
en(175 keys, no missing/extra in any locale), and placeholder structure (every$COUNT$/$RAM$/$VERSION$/$DATE$substitution token present inenis also present in the corresponding translated value). No locale repairs needed. - i18n key reference scan confirms every
data-i18n*attribute andchrome.i18n.getMessage/t(...)call resolves to a real key, and every key inen/messages.jsonis reachable from source (including the dynamic ones referenced via variable interpolation:t(statusKey)for the current-tab status andBADGES[reason].labelKeyfor the protect-reason badges). - Chrome MV3 best practices verified for the suspend pipeline:
chrome.tabs.discard()remains the canonical API;tab.lastAccessed(Chrome 121+) is feature-detected withtypeof === 'number'and gracefully falls back on 120;chrome.storage.sessioncorrectly used for the in-memorytabTimestampscache that survives worker restarts via re-seeding fromtab.lastAccessed;chrome.alarmsminimum delay (0.5 min in production) respected. The known quirk thattab.lastAccessedbecomesundefinedfor discarded tabs is handled correctly: every code path that reads it either guards with the typeof check or has already early-returned ontab.discarded.
Verifying this build
This release attaches the exact .zip uploaded to the Chrome Web Store. To verify it hasn't been tampered with:
sha256: ad5e3179f250108483b27ba5781c79bbbaa506d3726e3601ecb75842be0f677f
You can reproduce the build yourself by checking out v1.3.4 and zipping the extension files (everything except .git/, .github/, *.md, docs/).