mirror of
https://github.com/fluffos/fluffos
synced 2026-08-12 18:26:06 -04:00
fix(wasm-www): mask password prompts with CSS, never input.type=password
Reported live: iOS Safari kept showing its AutoFill quick-suggestion bar (passwords/cards/contacts icons) above the keyboard even during ordinary command typing, well after any password prompt had passed. Root cause: the command input toggled between type="text" and type="password" on the SAME persistent <input> element (driven by the telnet SGA/ECHO negotiation -- see onEcho()). WebKit's AutoFill heuristic sticks to an element as a credential field for the rest of the page's life once it's ever been type="password", regardless of the type reverting afterward. This mud never wants the browser's credential manager involved at all (autocomplete=off already says so) -- the masking need is purely visual. Replaced the type toggle with a `.masked` CSS class applying -webkit-text-security:disc (WebKit/Blink; not Firefox, but that only affects whether typed characters are legible, never functionality, and iOS/Chrome cover the overwhelming majority of this page's mobile traffic). input.type now never changes from "text"; updated the one other reader of it (the Enter-key handler's local-echo suppression) to check the session's serverEchoes flag directly instead. Verified against a real packed site: type stays "text" through the .masked toggle in both directions, the -webkit-text-security:disc computed style applies/clears correctly, and a masked field visibly renders bullet dots for typed text. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VyQCUoTo1Z93Py9aVFHQi1
This commit is contained in:
parent
5cc89de8ac
commit
eaa1a6ee13
1 changed files with 17 additions and 3 deletions
|
|
@ -185,6 +185,19 @@
|
|||
flex: 1; background: transparent; border: 0; outline: 0; color: var(--fg);
|
||||
font: inherit; padding: 10px 16px 10px 8px;
|
||||
}
|
||||
/* Password-style masking WITHOUT ever setting type="password": once an
|
||||
<input> has been type="password" even briefly, iOS/Safari's AutoFill
|
||||
heuristic sticks to it as a credential field for the rest of the
|
||||
page's life (the passwords/cards/contacts QuickType bar keeps showing
|
||||
above the keyboard even after switching back to type="text" --
|
||||
reported live). This mud never wants the browser's credential
|
||||
manager involved at all (autocomplete=off already says so) -- the
|
||||
masking is purely visual, so do it with CSS instead and never touch
|
||||
`type`. -webkit-text-security is WebKit/Blink-only (not in Firefox);
|
||||
acceptable here since it only affects whether typed characters are
|
||||
LEGIBLE, never functionality, and iOS/Chrome cover the overwhelming
|
||||
majority of mobile traffic this page sees. */
|
||||
#cmd.masked { -webkit-text-security: disc; }
|
||||
.modal-overlay {
|
||||
position: fixed; inset: 0; background: rgba(4, 6, 10, 0.72);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
|
|
@ -833,7 +846,8 @@ function makeSession() {
|
|||
s.telnet.onText = (t) => s.term.write(t);
|
||||
s.telnet.onEcho = (on) => {
|
||||
s.serverEchoes = on;
|
||||
if (view === s && !s.charMode) input.type = on ? 'password' : 'text';
|
||||
// CSS-only masking, never input.type -- see the #cmd.masked rule.
|
||||
if (view === s && !s.charMode) input.classList.toggle('masked', on);
|
||||
};
|
||||
s.telnet.onCharMode = (on) => {
|
||||
if (on === s.charMode) return;
|
||||
|
|
@ -898,7 +912,7 @@ function applyInputState(s) {
|
|||
status.textContent = s.disconnected ? 'disconnected'
|
||||
: s.connId >= 0 ? 'connected (conn ' + s.connId + ')'
|
||||
: 'connecting…';
|
||||
input.type = s.serverEchoes ? 'password' : 'text';
|
||||
input.classList.toggle('masked', s.serverEchoes);
|
||||
input.disabled = s.disconnected || s.connId < 0;
|
||||
refit(s);
|
||||
if (!input.disabled && view === s) input.focus();
|
||||
|
|
@ -1007,7 +1021,7 @@ input.addEventListener('keydown', (ev) => {
|
|||
const s = activeGame;
|
||||
const line = input.value;
|
||||
input.value = '';
|
||||
if (input.type !== 'password') s.term.write(line + '\r\n');
|
||||
if (!s.serverEchoes) s.term.write(line + '\r\n');
|
||||
s.sendData(Array.from(utf8enc.encode(line + '\r\n')));
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue