Skip to content

Commit ced1427

Browse files
ralyodioclaude
andcommitted
fix(tor): default OFF reliably (session storage) + trigger .onion on nav error (v3.2.15)
- Default-off regression: onStartup wasn't firing, so torEnabled carried over and the .onion auto-enable skipped. Now use chrome.storage.session (wiped on browser restart) to tell a fresh launch from a SW restart: fresh start clears any stale Tor state; mid-session SW restart re-applies it. Tor is off on every fresh launch. - .onion trigger: drive it off webNavigation.onErrorOccurred (fires exactly when the onion fails to resolve) instead of onBeforeNavigate — simpler + reliable. Logs to the SW console; interstitial + retry as before. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 14fc63a commit ced1427

26 files changed

Lines changed: 78 additions & 61 deletions

File tree

apps/desktop/extensions/ai-sidebar/background.js

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ async function enableTor(auto = false) {
124124
await chrome.privacy.network.webRTCIPHandlingPolicy.set({ value: 'disable_non_proxied_udp' });
125125
} catch (_) { /* privacy controlled elsewhere */ }
126126
await chrome.storage.local.set({ torEnabled: true, torAuto: auto });
127+
// session storage is wiped on browser restart → marks Tor as on THIS session.
128+
try { await chrome.storage.session.set({ torSession: { auto } }); } catch (_) { /* no-op */ }
127129
await setTorBadge(true);
128130
}
129131

@@ -137,6 +139,7 @@ async function disableTor() {
137139
try { await chrome.proxy.settings.clear({ scope: 'regular' }); } catch (_) { /* already clear */ }
138140
try { await chrome.privacy.network.webRTCIPHandlingPolicy.clear({}); } catch (_) { /* already clear */ }
139141
await chrome.storage.local.set({ torEnabled: false, torAuto: false });
142+
try { await chrome.storage.session.remove('torSession'); } catch (_) { /* no-op */ }
140143
await setTorBadge(false);
141144
}
142145

@@ -216,48 +219,62 @@ chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
216219
}
217220
});
218221

219-
// Tor defaults OFF on every fresh browser start. Nobody should be routed through
220-
// Tor unless they ask — and the daemon isn't running yet at launch, so a
221-
// left-over proxy would just break browsing. (Within a session the proxy is a
222-
// persisted setting, so Tor stays on across service-worker restarts on its own.)
223-
chrome.runtime.onStartup.addListener(() => {
224-
disableTor().catch(() => {});
225-
});
222+
// Tor defaults OFF on every fresh browser start — nobody is routed through Tor
223+
// unless they ask (or load a .onion). chrome.storage.session is wiped on browser
224+
// restart, so it tells a fresh launch from a service-worker restart mid-session.
225+
(async () => {
226+
try {
227+
const { torSession } = await chrome.storage.session.get('torSession');
228+
if (torSession) {
229+
// Same session, SW just restarted → keep Tor on (re-apply the proxy).
230+
await enableTor(!!torSession.auto);
231+
} else {
232+
// Fresh browser start. If local still says Tor was on (carried over from
233+
// the last run), clear it + any persisted proxy. Otherwise leave the
234+
// proxy untouched.
235+
const { torEnabled } = await chrome.storage.local.get('torEnabled');
236+
if (torEnabled) await disableTor();
237+
}
238+
} catch (_) { /* best effort */ }
239+
})();
226240

227-
// Auto-enable Tor when navigating to a .onion site (they only resolve through
228-
// Tor). Redirect to a "Connecting to Tor…" page so there's no raw DNS error,
229-
// bring Tor up, then send the tab to the onion once it routes.
230-
chrome.webNavigation.onBeforeNavigate.addListener(async (details) => {
231-
if (details.frameId !== 0) return; // top-level navigations only
232-
let host;
233-
try { host = new URL(details.url).hostname; } catch (_) { return; }
234-
if (!host.endsWith('.onion')) return;
241+
// Auto-enable Tor for .onion sites (they only resolve through Tor). A .onion
242+
// with Tor off fails DNS → onErrorOccurred fires; that's our trigger. We show a
243+
// "Connecting to Tor…" page, bring Tor up, then send the tab to the onion.
244+
const onionInProgress = new Set();
235245

246+
async function handleOnionNavigation(onion, tabId) {
247+
if (tabId == null || tabId < 0 || onionInProgress.has(tabId)) return;
236248
const { torEnabled } = await chrome.storage.local.get('torEnabled');
237-
const onion = details.url;
238-
const tabId = details.tabId;
239-
240-
// If Tor is already on, the navigation will resolve through it — leave it.
241-
if (torEnabled) return;
249+
if (torEnabled) return; // already routing through Tor
242250

243-
// Swap the failing onion navigation for the connecting page.
244-
const interstitial = chrome.runtime.getURL('onion-connecting.html') + '?u=' + encodeURIComponent(onion);
245-
try { await chrome.tabs.update(tabId, { url: interstitial }); } catch (_) { return; }
251+
onionInProgress.add(tabId);
252+
console.log('[tron-tor] .onion detected, connecting Tor:', onion);
253+
try {
254+
const interstitial = chrome.runtime.getURL('onion-connecting.html') + '?u=' + encodeURIComponent(onion);
255+
try { await chrome.tabs.update(tabId, { url: interstitial }); } catch (_) { /* tab gone */ }
246256

247-
const started = await startTorViaHelper();
248-
if (started.error === 'unreachable' || started.error === 'tor-not-installed') {
249-
chrome.runtime.sendMessage({ type: 'onion-error', reason: started.error }).catch(() => {});
250-
return;
251-
}
252-
const result = await waitForTor((pct) => {
253-
chrome.runtime.sendMessage({ type: 'tor-progress', pct }).catch(() => {});
254-
});
255-
if (result.ready) {
256-
await enableTor(true); // auto: released when the .onion tabs close
257-
try { await chrome.tabs.update(tabId, { url: onion }); } catch (_) { /* tab gone */ }
258-
} else {
259-
chrome.runtime.sendMessage({ type: 'onion-error', reason: result.error || 'tor-exited' }).catch(() => {});
257+
const started = await startTorViaHelper();
258+
if (started.error === 'unreachable' || started.error === 'tor-not-installed') {
259+
chrome.runtime.sendMessage({ type: 'onion-error', reason: started.error }).catch(() => {});
260+
return;
261+
}
262+
const result = await waitForTor((pct) => {
263+
chrome.runtime.sendMessage({ type: 'tor-progress', pct }).catch(() => {});
264+
});
265+
if (result.ready) {
266+
await enableTor(true); // auto: released when the .onion tabs close
267+
try { await chrome.tabs.update(tabId, { url: onion }); } catch (_) { /* tab gone */ }
268+
} else {
269+
chrome.runtime.sendMessage({ type: 'onion-error', reason: result.error || 'tor-exited' }).catch(() => {});
270+
}
271+
} finally {
272+
onionInProgress.delete(tabId);
260273
}
274+
}
275+
276+
chrome.webNavigation.onErrorOccurred.addListener((d) => {
277+
if (d.frameId === 0 && isOnionUrl(d.url)) handleOnionNavigation(d.url, d.tabId);
261278
});
262279

263280
// Auto-disable Tor once the last .onion tab is gone (only if we auto-enabled it).

apps/desktop/extensions/ai-sidebar/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "TronBrowser",
4-
"version": "3.2.14",
4+
"version": "3.2.15",
55
"description": "TronBrowser — privacy-first, AI-native. Branded new tab, private search, CoinPay login, and a bring-your-own-keys AI sidebar.",
66
"icons": {
77
"16": "icons/icon-16.png",

apps/desktop/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tronbrowser/desktop",
3-
"version": "3.2.14",
3+
"version": "3.2.15",
44
"private": true,
55
"description": "Desktop shell for the TronBrowser Chromium fork",
66
"type": "module",

apps/docs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tronbrowser/docs",
3-
"version": "3.2.14",
3+
"version": "3.2.15",
44
"private": true,
55
"description": "Documentation site",
66
"type": "module",

apps/extensions/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tronbrowser/extensions",
3-
"version": "3.2.14",
3+
"version": "3.2.15",
44
"private": true,
55
"description": "TronBrowser extension store — pay $1, list your MV3 extension (tronbrowser.dev/store)",
66
"type": "module",

apps/mobile/app.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"slug": "tronbrowserdev",
55
"owner": "profullstack",
66
"scheme": "tronbrowser",
7-
"version": "3.2.14",
7+
"version": "3.2.15",
88
"orientation": "portrait",
99
"userInterfaceStyle": "dark",
1010
"platforms": [

apps/mobile/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tronbrowser/mobile",
3-
"version": "3.2.14",
3+
"version": "3.2.15",
44
"private": true,
55
"description": "TronBrowser mobile (Expo / React Native) — Phase 2",
66
"type": "module",

apps/web/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tronbrowser/web",
3-
"version": "3.2.14",
3+
"version": "3.2.15",
44
"private": true,
55
"description": "TronBrowser marketing site + web dashboard",
66
"type": "module",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "tronbrowser",
3-
"version": "3.2.14",
3+
"version": "3.2.15",
44
"private": true,
55
"description": "TronBrowser.dev — open-source, privacy-first, AI-native browser",
66
"packageManager": "pnpm@9.12.0",

packages/agent-runtime/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tronbrowser/agent-runtime",
3-
"version": "3.2.14",
3+
"version": "3.2.15",
44
"private": true,
55
"description": "Agent runtime: planner, executor, validator, memory, tools",
66
"type": "module",

0 commit comments

Comments
 (0)