Skip to content

feat(install): clear bloated profile caches on upgrade, add tron clean - #74

Merged
ralyodio merged 1 commit into
mainfrom
feat/upgrade-cache-gc
Aug 3, 2026
Merged

feat(install): clear bloated profile caches on upgrade, add tron clean#74
ralyodio merged 1 commit into
mainfrom
feat/upgrade-cache-gc

Conversation

@ralyodio

@ralyodio ralyodio commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #72, from the same debugging session.

What actually caused the slowdown

Not DNS, not TronBrowser's code, not the engine. The profile had grown to 3.9G, with 1.4G in Service Worker/CacheStorage alone. Clearing three directories took it to 534M and the sluggishness went away.

Service-worker CacheStorage is quota-managed per origin, so a few heavy sites can carry a profile into the gigabytes with nothing to stop them. Past roughly a gigabyte the cost stops being disk and becomes latency — the CacheStorage index is consulted on navigation, and scrolling and tab switching go with it. It degrades gradually and then suddenly, which is why it reads as "the browser broke today" when nothing changed at all.

What this adds

tron upgrade clears Cache, Code Cache and Service Worker once they exceed TRONBROWSER_CACHE_LIMIT_MB (default 1024; 0 disables). None of those hold bookmarks, passwords, history or cookies — it costs a re-download and nothing else, and you stay logged in everywhere. That's what makes it better than chrome://settings/clearBrowserData, where the only option that clears service workers also clears cookies and signs you out of everything.

The threshold is load-bearing: the auto-upgrade check runs daily, and clearing a healthy profile every day would cost every user a re-download for nothing.

tron clean does it on demand. Implemented inside the CLI rather than by re-running the installer — cleaning a bloated profile is exactly when you don't want to need the network. install.sh clean --if-large runs the same threshold-gated pass tron upgrade uses.

Neither path unlinks anything while the browser is running. The profile is memory-mapped; pulling it out from under Chromium gives you a corrupt profile rather than a clean one, so a running browser gets a warning instead.

Tests

apps/web/test/install-clean.test.ts runs the real install.sh against a fake profile:

  • caches are cleared; Bookmarks, Cookies, History, Login Data and IndexedDB survive
  • --if-large leaves a small profile alone, and clears past the limit
  • TRONBROWSER_CACHE_LIMIT_MB=0 disables the automatic pass but not an explicit tron clean
  • TRONBROWSER_DATA is respected, and the default location isn't touched when it's overridden
  • a missing profile is a no-op

8 tests pass. sh -n and dash -n clean.

The tron CLI's copy of this lives inside a <<'TRON' heredoc, so sh -n install.sh never parses it — a real gap in how this file has always been checked. I extracted the generated CLI and verified it separately with sh -n, dash -n, and a live run against a fake profile (freed 5MB, kept Bookmarks/Cookies/IndexedDB).

Not covered

do_upgrade's call into the cleanup isn't exercised by an automated test — do_upgrade resolves the latest release over the network. The function it calls is tested through clean --if-large; the one-line call site is by inspection.

🤖 Generated with Claude Code

… clean`

Chromium's disk caches have no ceiling that matters here. Service-worker
CacheStorage is quota-managed per origin, so a handful of heavy sites can
carry a profile into the gigabytes on their own. Past roughly a gigabyte
the cost stops being disk and starts being latency: the CacheStorage
index is consulted on navigation, and once bloated, scrolling and tab
switching go with it. The failure is gradual and then sudden, so it
reads as "the browser broke today" — a profile that had reached 3.9G,
with 1.4G of CacheStorage, is what prompted this. Clearing three
directories took it to 534M and the sluggishness went away.

`tron upgrade` now clears Cache, Code Cache and Service Worker once they
exceed TRONBROWSER_CACHE_LIMIT_MB (default 1024, 0 disables). None of
those hold bookmarks, passwords, history or cookies, so it costs a
re-download and nothing else — you stay logged in everywhere, which is
what makes this better than chrome://settings/clearBrowserData, where
clearing service workers means clearing cookies too.

The threshold matters: the auto-upgrade check runs daily, and clearing a
healthy profile every day would cost everyone a re-download for nothing.

`tron clean` does it on demand, implemented in the CLI rather than by
re-running the installer — cleaning a bloated profile is exactly when you
don't want to need the network. Neither path will unlink anything while
the browser is running; the profile is memory-mapped, and pulling it out
from under Chromium yields a corrupt profile rather than a clean one.

Tests cover the cleanup against a fake profile: caches go, bookmarks,
cookies, history, login data and IndexedDB stay, the threshold and the
kill switch are honored, and TRONBROWSER_DATA is respected. The `tron`
CLI's copy is generated inside a heredoc, so `sh -n` never sees it — it
was extracted and checked with sh, dash, and a live run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

ThreatCrush Security Scan

93 finding(s)

HIGH/CRITICAL: 6 | MEDIUM: 87

Severity Rule Location
HIGH js-unescaped-html-sink apps/extensions/public/store.js:545
HIGH manifest-typosquat apps/mobile/package.json:35
HIGH js-unescaped-html-sink apps/web/public/dns.js:101
HIGH secret-generic-api-key packages/storage/src/config.ts:51
HIGH secret-generic-credential packages/storage/src/config.ts:51
HIGH secret-generic-credential services/api/src/store/payments.test.ts:11
MEDIUM js-open-redirect apps/desktop/extensions/ai-sidebar/install-helper.js:96
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/media.js:28
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/media.js:33
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/media.js:56
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/newtab.js:232
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/newtab.js:261
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/newtab.js:331
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/options.js:305
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/settings-sections.js:24
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/sidepanel.js:76
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/sidepanel.js:164
MEDIUM insecure-temp-file apps/desktop/src/launcher.test.ts:21
MEDIUM insecure-temp-file apps/desktop/src/tor.test.ts:40
MEDIUM insecure-temp-file apps/desktop/src/tor.test.ts:44
MEDIUM insecure-temp-file apps/desktop/test/launcher.test.ts:92
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:77
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:92
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:93
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:104
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:107
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:110
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:155
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:163
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:175
MEDIUM sql-template-interpolation apps/extensions/public/store.js:176
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:222
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:225
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:227
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:230
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:282
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:289
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:292
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:302
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:307
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:319
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:419
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:425
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:429
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:449
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:468
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:477
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:481
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:497
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:506

…and 43 more. Full results in the Security tab.

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio marked this pull request as ready for review August 3, 2026 16:29
@ralyodio
ralyodio merged commit 809e8a3 into main Aug 3, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant