diff --git a/scripts/windows-smoke.mjs b/scripts/windows-smoke.mjs index a757340..1808d1b 100644 --- a/scripts/windows-smoke.mjs +++ b/scripts/windows-smoke.mjs @@ -11,6 +11,7 @@ // instead of failing, so the same script runs on main and on PR branches. import { writeFileSync, mkdirSync } from 'node:fs'; import { execSync } from 'node:child_process'; +import { createServer } from 'node:http'; import { chromium } from 'playwright-core'; const OUT = process.argv[2] || 'smoke-out'; @@ -150,21 +151,38 @@ else if (!kc.supported) record('keychain round trip', 'fail', 'secure_session_su else record('keychain round trip', kc.roundTrip && kc.restored ? 'pass' : 'fail', JSON.stringify(kc)); // 7. A foreign page loaded in the window must not get the microphone (#22). -await page.goto('https://example.com/').catch(() => undefined); -const foreignMic = await page.evaluate(async () => { - try { - const s = await navigator.mediaDevices.getUserMedia({ audio: true }); - s.getTracks().forEach((t) => t.stop()); - return 'ok'; - } catch (e) { - return e.name; - } +// Served locally on another port (a different origin, still a secure context), +// so the check doesn't depend on the runner reaching the internet. +const foreign = createServer((_, res) => { + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end('foreignforeign page'); }); -record( - 'microphone refused to a foreign page', - foreignMic === 'NotAllowedError' ? 'pass' : 'info', - `${foreignMic}${foreignMic === 'ok' ? ' (build without the #22 origin check)' : ''}`, -); +await new Promise((r) => foreign.listen(9333, '127.0.0.1', r)); +const FOREIGN = 'http://localhost:9333/'; +await page.goto(FOREIGN).catch(() => undefined); +if (!page.url().startsWith(FOREIGN)) { + record('microphone refused to a foreign page', 'fail', `navigation did not happen (at ${page.url()})`); +} else { + const foreignMic = await page.evaluate(async () => { + try { + const s = await navigator.mediaDevices.getUserMedia({ audio: true }); + s.getTracks().forEach((t) => t.stop()); + return 'ok'; + } catch (e) { + return e.name; + } + }); + const guarded = cfg.desktopCallOrigin !== undefined; // builds with #22 also carry #43 + let status = 'info'; + if (foreignMic === 'NotAllowedError') status = 'pass'; + else if (guarded) status = 'fail'; + record( + 'microphone refused to a foreign page', + status, + `${foreignMic} at ${page.url()}${status === 'info' ? ' (build without the #22 origin check)' : ''}`, + ); +} +foreign.close(); await page.goto(APP).catch(() => undefined); await page.screenshot({ path: `${OUT}/02-end.png` }).catch(() => undefined);