diff --git a/universal-runtime/manager.py b/universal-runtime/manager.py index e78d1b8..76eec6f 100644 --- a/universal-runtime/manager.py +++ b/universal-runtime/manager.py @@ -115,24 +115,39 @@ _AUTOFILL_CONTENT_JS = r""" function tryFill() { const p = findPassField(); - // No visible password field = not a login form; stop to avoid filling app inputs - if (!p) return; - const u = findUserField(p); - // Fill login FIRST so password-triggered re-render doesn't clear it - if (CREDS.login && u) { - if (setNativeValue(u, CREDS.login)) { - console.log('[PortalAutofill] user filled'); + + // Fill by specific attrs even on two-step forms (where password isn't visible yet) + const uSpec = findUserFieldByAttrs(); + if (CREDS.login && uSpec) { + if (setNativeValue(uSpec, CREDS.login)) { + console.log('[PortalAutofill] user filled (specific)'); } } - if (CREDS.password && p) { + + // Without a visible password field don't use broad fallback — + // prevents filling generic app inputs (e.g. R7-Office font selector) + if (!p) return; + + // With password field: also try proximity / broad fallback for username + const u = uSpec || findUserFieldNearPassword(p) || + Array.from(document.querySelectorAll('input[type="text"], input:not([type])')) + .find(isVisible) || null; + + if (CREDS.login && u && u !== uSpec) { + if (setNativeValue(u, CREDS.login)) { + console.log('[PortalAutofill] user filled (fallback)'); + } + } + if (CREDS.password) { if (setNativeValue(p, CREDS.password)) { console.log('[PortalAutofill] password filled'); } } - // Some apps (e.g. Zabbix) clear username after password events — re-fill if needed - if (CREDS.login && u && u.value !== CREDS.login) { - setNativeValue(u, CREDS.login); - console.log('[PortalAutofill] user re-filled after password'); + // Re-fill guard: some apps clear username after password events + const uFinal = u || uSpec; + if (CREDS.login && uFinal && uFinal.value !== CREDS.login) { + setNativeValue(uFinal, CREDS.login); + console.log('[PortalAutofill] user re-filled'); } }