807418099580
TEST_WS_LOCAL + TEST_SUBNET_DETECT handlers in messages.ts for service-worker connectivity probe (v2.38.13)
- time
- 2026-05-12 15:11 UTC · 5 months ago
- machine
- koh2
- parent
- 717b4cb8afca
↓ peach-browser-80741809.tar.gzatlas at this save
files changed5 files
manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/background/messages.ts+92 −0src/shared/types.ts+2 −0manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach",4- "version": "2.38.12",4+ "version": "2.38.13",55 "description": "Zero-knowledge password manager",66 "browser_specific_settings": {77 "gecko": {manifest.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach",4- "version": "2.38.12",4+ "version": "2.38.13",55 "description": "Zero-knowledge password manager",66 "action": {77 "default_popup": "src/popup/index.html",package.json+1 −1
@@ -1,6 +1,6 @@11 {22 "name": "peach",3- "version": "2.38.12",3+ "version": "2.38.13",44 "description": "Zero-knowledge password manager",55 "type": "module",66 "scripts": {src/background/messages.ts+92 −0
@@ -1246,6 +1246,98 @@12461246 const result = await discoverDevice(subnet, "000000000000000000000000000000000000000000000000000000000000000000");12471247 return { ok: true, data: { elapsed: Date.now() - start, found: !!result } };12481248 }1249+ case 'TEST_WS_LOCAL': {1250+ const { ip } = msg.payload as { ip: string };1251+1252+ return new Promise((resolve) => {1253+ const log: string[] = [];1254+ log.push(`Attempting ws://${ip}:44100 from service worker...`);1255+1256+ let ws: WebSocket;1257+ let settled = false;1258+ const settle = (result: MessageResponse) => {1259+ if (!settled) { settled = true; resolve(result); }1260+ };1261+1262+ try {1263+ ws = new WebSocket(`ws://${ip}:44100`);1264+1265+ ws.onopen = () => {1266+ log.push('SUCCESS: WebSocket connected');1267+ ws.close();1268+ settle({ ok: true, data: { log } });1269+ };1270+1271+ ws.onerror = (e) => {1272+ log.push(`FAILED: onerror fired — ${String(e)}`);1273+ settle({ ok: false, error: 'ws_error', data: { log } });1274+ };1275+1276+ ws.onclose = (e) => {1277+ if (e.code !== 1000) {1278+ log.push(`CLOSED unexpectedly: code=${e.code} reason=${e.reason}`);1279+ settle({ ok: false, error: 'ws_closed', data: { code: e.code, log } });1280+ }1281+ };1282+1283+ setTimeout(() => {1284+ try { ws.close(); } catch {}1285+ log.push('FAILED: 5 second timeout — connection never opened');1286+ settle({ ok: false, error: 'timeout', data: { log } });1287+ }, 5000);1288+1289+ } catch (err) {1290+ log.push(`FAILED: WebSocket constructor threw — ${String(err)}`);1291+ settle({ ok: false, error: 'constructor_threw', data: { log } });1292+ }1293+ });1294+ }1295+1296+ case 'TEST_SUBNET_DETECT': {1297+ return new Promise((resolve) => {1298+ try {1299+ // RTCPeerConnection availability varies by context — this is what we're testing1300+ // eslint-disable-next-line @typescript-eslint/no-explicit-any1301+ const RTC = (globalThis as any).RTCPeerConnection as (new (cfg: object) => RTCPeerConnection) | undefined;1302+ if (!RTC) {1303+ resolve({ ok: false, error: 'RTCPeerConnection is not defined' });1304+ return;1305+ }1306+ const pc = new RTC({ iceServers: [] });1307+ pc.createDataChannel('');1308+ pc.createOffer().then((o) => pc.setLocalDescription(o));1309+1310+ const candidates: string[] = [];1311+ const timer = setTimeout(() => {1312+ pc.close();1313+ if (candidates.length === 0) {1314+ resolve({ ok: false, error: 'no_candidates', data: { candidates } });1315+ } else {1316+ const subnet = candidates[0].match(/(\d+\.\d+\.\d+)\.\d+/)?.[1];1317+ resolve({ ok: true, data: { subnet, candidates } });1318+ }1319+ }, 2000);1320+1321+ pc.onicecandidate = (e) => {1322+ if (!e.candidate) return;1323+ const m = e.candidate.candidate.match(/(\d+\.\d+\.\d+\.\d+)/);1324+ if (m && !m[1].startsWith('127')) candidates.push(m[1]);1325+ };1326+1327+ pc.onicegatheringstatechange = () => {1328+ if (pc.iceGatheringState === 'complete') {1329+ clearTimeout(timer);1330+ pc.close();1331+ const subnet = candidates[0]?.match(/(\d+\.\d+\.\d+)\.\d+/)?.[1];1332+ resolve({ ok: candidates.length > 0, data: { subnet, candidates } });1333+ }1334+ };1335+ } catch (err) {1336+ resolve({ ok: false, error: String(err) });1337+ }1338+ });1339+ }1340+12491341 // --- end test handlers ---12501342 default:12511343 return { ok: false, error: "unknown message type" };src/shared/types.ts+2 −0
@@ -309,6 +309,8 @@309309 | "TEST_LOCAL_WEBSOCKET"310310 | "TEST_SUBNET_DETECTION"311311 | "TEST_SUBNET_SCAN"312+ | "TEST_WS_LOCAL"313+ | "TEST_SUBNET_DETECT"312314 // Content-script-bound message types — sent BY the background TO content313315 // scripts. They never reach messages.ts's switch. Kept in this union so314316 // existing call sites type-check; do not add cases for them in the