Files
Deng Liuanddengliu af19880390 feat(plugins): PTY session bridge for plugin web views (#2038)
A plugin web view can open interactive PTY sessions (spawn, input, resize, kill, streamed output and exit). Spawning requires the exact granted `process:<program>` and its pinned executable, with no PATH re-resolution or fallback shell; the cwd is the trusted project, arguments, environment (append-only) and sizes are validated, and at most eight sessions run per plugin. A frame can only drive the sessions it opened; output is acknowledged chunk by chunk and input/output are bounded. Sessions end on permission change, reload, disable, uninstall, frame teardown or window close. Requires API ^1.3; adds a web-pty test fixture. Verified on macOS; Windows/Linux not run.

Co-authored-by: dengliu <[email protected]>
2026-11-08 03:29:36 +08:00

28 lines
2.1 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html><head><meta charset="utf-8"><title>PTY Probe</title>
<style>
body { background: var(--openidea-bg); color: var(--openidea-fg); font-family: var(--openidea-font-mono, monospace); font-size: var(--openidea-font-size, 13px); padding: 12px; }
button, input { font: inherit; padding: 6px; } pre { white-space: pre-wrap; overflow-wrap: anywhere; } form { display: flex; gap: 4px; } input { flex: 1; min-width: 0; }
</style></head><body>
<h2>Web PTY Probe</h2><p id="isolation"></p>
<button id="start">Start bash</button> <button id="stop">Stop</button> <button id="resize">Resize to 100 × 30</button>
<pre id="output" aria-live="polite"></pre>
<form id="input"><input id="command" aria-label="Terminal input" placeholder="Type a shell command"><button>Send</button></form>
<script>
const output = document.querySelector('#output');
const send = (op, args = {}) => openidea.postMessage(JSON.stringify({ op, sessionId: 'probe', ...args }));
document.querySelector('#isolation').textContent = `IPC globals: ${typeof window.__TAURI_INTERNALS__}; parent access: ` + (() => { try { return parent.document.title; } catch { return 'blocked'; } })();
openidea.onMessage(text => {
let m; try { m = JSON.parse(text); } catch { return; }
if (m.op === 'pty-data') {
output.textContent = (output.textContent + m.data).slice(-65536);
send('pty-ack', { sequence: m.sequence });
} else if (m.op === 'pty-error') output.textContent += '\nERROR: ' + m.error + '\n';
else if (m.op === 'pty-exit') output.textContent += '\nEXIT: ' + m.exitCode + '\n';
});
document.querySelector('#start').onclick = () => send('pty-spawn', { program: 'bash', args: ['--noprofile', '--norc', '-i'], cols: 100, rows: 30 });
document.querySelector('#stop').onclick = () => send('pty-kill');
document.querySelector('#resize').onclick = () => send('pty-resize', { cols: 100, rows: 30 });
document.querySelector('#input').onsubmit = e => { e.preventDefault(); send('pty-input', { data: document.querySelector('#command').value + '\r' }); document.querySelector('#command').value = ''; };
</script></body></html>