github gioxx/MarvellousSuspender v9.0.3

5 hours ago

A stability-and-polish release: a big memory/OOM hardening pass, automatic favicon recovery on Chromium forks, a server-side move of the Drive OAuth exchange, plus several new options (battery-power timeout, "never suspend app windows", tab-group suspend/unsuspend, reopen-scrolled-to-top) and a "What's new" screen after updates.

Highlights

  • Suspended-tab favicons recover on their own after a browser restart (#474, #397/#260 lineage): the previous startup repair fired once off chrome.runtime.onStartup plus a session-storage sentinel; on Brave / Vivaldi / Dia that pass was routinely lost (worker recycled mid-run, or tabs not restored yet) and never retried, so tabs kept the extension icon until a manual Tab Health reload. A dedicated, onStartup-independent backstop now re-checks via a self-re-arming chrome.alarms alarm and on the first activation of a suspended tab, only standing down after two consecutive clean passes (so a slow "continue where you left off" restore isn't cut short). The #449 "Repair favicons now" debug action stays as the manual escape hatch. Verified live on Brave 152.
  • A rare out-of-memory crash, reproduced and fixed at the root (#464, #466, #467, #473): the log buffer moved from a single broadcast chrome.storage.local blob to per-record IndexedDB (no cross-context onChanged fan-out), captureLogs growth is bounded and trimmed on a schedule, and initialiseSuspendedTab() is now concurrency-capped so a burst of tab restores can't spike memory. Mostly invisible unless you run captureLogs, but the underlying changes make the extension more resilient regardless.
  • Drive OAuth token exchange moved server-side to tms-oauth-proxy (#476, #440, #437): the OAuth client secret is no longer shipped in the extension package. On browsers where chrome.identity.getAuthToken() doesn't work (Brave, Vivaldi), auto-backup now uses authorization-code + PKCE with a long-lived refresh_token renewed by a direct token call — no tab, no ambient-session dependency — replacing the short-lived implicit-flow fallback that dropped Drive accounts after a backup or two. Existing Brave/Vivaldi users: reconnect once (Options → Backup → Connect) after updating.
  • Separate auto-suspend timeout for battery power (#252): a new "Suspend tabs on battery power after" select alongside the AC timeout — suspend more aggressively when unplugged without touching the plugged-in value. Defaults to "Same as when plugged in".
  • "Never suspend app windows" (#154): a new option (on by default, like the pinned/audio/active protections) that keeps tabs in an app-mode window — installed PWAs, or a site opened via "Create Shortcut → Open as window" — from being auto-suspended.
  • Suspend / unsuspend every tab in a tab group (#133, thanks @mherkazandjian): new page and tab-strip context-menu items plus two bindable keyboard shortcuts, acting on every tab sharing the clicked tab's group.
  • "What's new" screen after an update: a one-time modal on the Settings page showing just the current version's changes, backed by a new short, user-facing CHANGELOG_USER.md kept separate from the detailed engineering changelog.
  • "Always reopen suspended tabs scrolled to the top" (#308): opt-in — the tab reopens at the top of the page instead of wherever it was scrolled to, overriding #section anchors.
  • Opt-in: reload also unsuspends background tabs (#158): reloading a suspended tab you're not looking at (e.g. via a multi-tab selection) can now unsuspend it; off by default.
  • Blinking white background when switching between suspended tabs, fixed (#168): a standalone critical.css (plus a render-blocking criticalTheme.js for explicit theme overrides) paints the background immediately instead of showing the browser default until the real stylesheets load. Reported as far back as v7.1.6.2.

Also in this release

  • Debug page: "Repair favicons now" action (#449), a live power-source indicator (#252), a larger rotating buffer for the downloadable report (#444), a "reset changelog seen flag" action, and a compacted Controls layout.
  • Suspended page dark-mode polish (#446): dimmed title/URL text and classic-mascot artwork; the reload hotkey link toned down from accent-blue to a subdued gray at a contrast-safe value (#478).
  • Battery-specific timeout: now reacts immediately to unplugging (it needed a manual trigger before), works on Chrome below 150, and stays configurable even when the AC timeout is set to "Never".
  • Multi-tab reload determinism (#158): reloading a selection of suspended tabs no longer unsuspends only a random subset.
  • checkQueue hardening: an uncaught exception no longer strands a concurrency slot; a job that legitimately requeues several times isn't killed by a stale timeout; a single huge-resolution favicon can't blow the check budget.
  • Legacy mascot artwork now uses TMS's own modified assets instead of the raw original TheGreatSuspender files, and Tab Health / the favicon backstop count both mascot-icon variants correctly.
  • Repo/CI: structured GitHub issue forms replace the free-form template (#479), two dead inherited workflows removed (#479, #480), and a js-yaml CVE + a brace-expansion DoS patched in dev deps.
  • Smaller: single Drive backup downloads no longer nested under tms-backups/ (#451); Health/About intro text restyled to match the other internal pages; debug log view shows the date for entries not from today.

See CHANGELOG.md for the full, fix-by-fix list.


What's Changed

  • feat(tab-groups): add suspend/unsuspend all tabs in this group (#133) by @mherkazandjian in #438
  • fix(gsBackup): Drive auth fallback to PKCE with refresh_token by @gioxx in #440
  • feat(options): opt-in reload-unsuspend for background tabs by @gioxx in #443
  • fix(tgs): retry initTab message send to suspended pages by @gioxx in #445
  • fix(suspended): dim title/URL text and classic mascot artwork in dark mode by @gioxx in #447
  • fix(gsBackup): don't nest single Drive backup downloads under tms-backups/ by @gioxx in #451
  • fix(gsTabQueue): reset job timeout on requeue instead of letting the original deadline stand by @gioxx in #452
  • feat(debug): add on-demand favicon repair action by @gioxx in #453
  • fix(tgs): switch initTab retry to exponential backoff by @gioxx in #457
  • feat(options): add option to disable scroll-position restore on unsuspend by @gioxx in #458
  • feat(options): add separate auto-suspend timeout for battery power by @gioxx in #459
  • feat(debug): larger rotating buffer for downloadable report (#444) by @gioxx in #463
  • fix(gsUtils): log buffer eager load, clear-log race, captureLogs scope by @gioxx in #464
  • fix: address 5 findings from Codex review of master vs v9.0.2 by @gioxx in #465
  • fix(gsUtils): remove dead log-buffer duplication, cap unbounded pendingEntries growth by @gioxx in #466
  • fix(gsUtils): coalesce log-append messages to fix flush-burst sluggishness by @gioxx in #467
  • fix(debug): guard fetchTabInfo() against overlapping focus-triggered runs by @gioxx in #470
  • fix(debug): debounce fetchTabInfo() to at most one run per second by @gioxx in #471
  • fix(debug): let getDebugInfo() actually recover an unresponsive tab by @gioxx in #472
  • fix(tgs): cap concurrent initialiseSuspendedTab() to prevent OOM crash on tab-restore burst by @gioxx in #473
  • feat(changelog): short user-facing What's new file, separate from CHANGELOG.md by @gioxx in #475
  • Drive PKCE token exchange: move client secret server-side (tms-oauth-proxy) by @gioxx in #476
  • fix(suspended): prevent white background flash switching tabs (#168) by @gioxx in #477
  • fix(suspended): tone down the reload hotkey link's color by @gioxx in #478
  • chore(github): structured issue forms + drop stale IssueAssignment workflow by @gioxx in #479
  • ci: remove stale.yml (dead probot Stale config) by @gioxx in #480
  • feat(gsTabSuspendManager): never auto-suspend tabs in app-mode windows by @gioxx in #481
  • fix(favicon): onStartup-independent backstop for automatic favicon repair on Chromium forks (#474) by @gioxx in #484

Additional polish merged directly to master: a js-yaml CVE + brace-expansion DoS dep patch, the "reset changelog seen flag" debug action and Controls-layout compaction, legacy mascot artwork sourced from TMS 8.1.6 instead of raw TGS, the "What's new" changelog modal itself, sectionDesc restyling on Health/About, the Drive auth-method label update for the OAuth proxy, the debug log-view date fix, the 9.0.3 version bump, and the CHANGELOG date stamp.

New Contributors

Full Changelog: v9.0.2...v9.0.3

Don't miss a new MarvellousSuspender release

NewReleases is sending notifications on new releases.