/** * Muse Autofill Suppression * * Disables native browser autofill (WebView2/WKWebView/WebKitGTK) so that * the Muse password vault is the only credential source for form fields. * * Why: System WebView engines may show their own password save/autofill UIs * which conflict with our Stronghold-backed vault. We suppress them by: * 1. Setting autocomplete="off" on all form/input elements * 2. Using autocomplete="new-password" on password fields (tells browsers not to autofill) * 3. Adding data-* attributes that third-party password managers check * 4. Intercepting dynamically created inputs via MutationObserver * * Platform notes: * - Windows WebView2: general_autofill_enabled(false) is also set via Rust builder. * Password save is already off by default (IsPasswordAutosaveEnabled=false). * - macOS WKWebView: No public API exists. This JS approach + the Rust * .general_autofill_enabled(false) builder call (noop on mac but future-proof). * - Linux WebKitGTK: No built-in password manager UI — this is purely defensive. */ (function() { if (window.__museAutofillSuppressed) return; window.__museAutofillSuppressed = true; function suppress(el) { if (!el || !el.setAttribute) return; var tag = el.tagName; if (tag === 'FORM') { el.setAttribute('autocomplete', 'off'); } else if (tag === 'INPUT') { var type = (el.type || '').toLowerCase(); if (type === 'password') { // "new-password" tells browsers: don't autofill existing passwords el.setAttribute('autocomplete', 'new-password'); } else if (type === 'email' || type === 'text' || type === 'tel') { el.setAttribute('autocomplete', 'off'); } // Suppress third-party password managers too el.setAttribute('data-lpignore', 'true'); // LastPass el.setAttribute('data-form-type', 'other'); // Dashlane el.setAttribute('data-1p-ignore', 'true'); // 1Password } } function suppressAll() { document.querySelectorAll('form, input').forEach(suppress); } // Initial pass if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', suppressAll); } else { suppressAll(); } // Watch for dynamically added forms/inputs (SPAs) var observer = new MutationObserver(function(mutations) { for (var i = 0; i < mutations.length; i++) { var added = mutations[i].addedNodes; for (var j = 0; j < added.length; j++) { var node = added[j]; if (node.nodeType !== 1) continue; suppress(node); if (node.querySelectorAll) { node.querySelectorAll('form, input').forEach(suppress); } } } }); observer.observe(document.documentElement, { childList: true, subtree: true }); })();