fix(autofill): honest result reporting + restore maximized from tray
Bug 1: a maximized window trayed via the quick-search fill flow came back "normal" on the next restore. ExecuteAutofill minimizes the window BEFORE MinimizeToTray snapshots the placement, so the snapshot said SHOWMINIMIZED and the never-restore-minimized guard forced SHOWNORMAL. Now honours WPF_RESTORETOMAXIMIZED (Windows keeps the pre-minimize state in flags). Bug 2: filling into an elevated app (admin Notepad) showed "password sent" while UIPI silently discarded the keystrokes (SendInput even reports success). ExecuteAutofill is now a function: it checks the target process elevation up front (can't-open counts as elevated) and returns False without typing. UMainForm feeds the result to JS via Bridge.onAutofillResult; the quick-search success toast is deferred until Delphi confirms, and a failure shows "Autofill blocked - the target window runs as administrator". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -167,6 +167,23 @@ function autofillScore(entry, titleLower) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Success toast deferred until Delphi confirms the keystrokes were sent.
|
||||
// Quick-search sets this label before calling executeAutofill; Delphi fires
|
||||
// Bridge.onAutofillResult(ok) → we toast the label (ok) or an honest
|
||||
// failure (elevated target — UIPI silently drops our SendInput).
|
||||
let autofillPendingToast = '';
|
||||
|
||||
function autofillReportResult(ok) {
|
||||
const label = autofillPendingToast;
|
||||
autofillPendingToast = '';
|
||||
if (ok) {
|
||||
if (label) toast(label);
|
||||
} else {
|
||||
toast('Autofill blocked — the target window runs as administrator. ' +
|
||||
'Copy the password instead.', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Called by Bridge.onAutofillRequest when a hotkey fires.
|
||||
// kind: 'full' = Ctrl+Shift+L (user + Tab + pwd) ; 'password' = Ctrl+Shift+P.
|
||||
async function autofillHandleRequest(windowTitle, kind) {
|
||||
|
||||
@@ -113,6 +113,12 @@ const Bridge = (() => {
|
||||
autofillHandleRequest(windowTitle, kind || 'full');
|
||||
},
|
||||
|
||||
// Called by Delphi after cmd://autofill/execute with whether the
|
||||
// keystrokes were actually sent (false = elevated target, UIPI).
|
||||
onAutofillResult(ok) {
|
||||
autofillReportResult(!!ok);
|
||||
},
|
||||
|
||||
// Called by Delphi on Ctrl+Shift+A. Opens the new-entry modal with
|
||||
// the foreground window title pre-filled (browser suffix stripped).
|
||||
onNewEntryFromTitle(windowTitle) {
|
||||
|
||||
+5
-3
@@ -115,8 +115,10 @@ async function quickSearchPickEntry(entry, mode) {
|
||||
if (mode === 'user') {
|
||||
const u = entry.username || '';
|
||||
if (!u) { toast('No username on this entry', 'warning'); return; }
|
||||
// Toast deferred to Bridge.onAutofillResult — Delphi reports
|
||||
// whether the keystrokes actually landed (elevated target = no).
|
||||
autofillPendingToast = entryDisplayName(entry) + ' · username sent';
|
||||
if (Bridge.active) Bridge.executeAutofill(u, '', quickSearchHideAfter, 'user');
|
||||
toast(entryDisplayName(entry) + ' · username sent');
|
||||
} else {
|
||||
const pwd = await decryptPwd(entry.encrypted_password, entry.iv);
|
||||
if (pwd === '[ERROR]') {
|
||||
@@ -131,9 +133,9 @@ async function quickSearchPickEntry(entry, mode) {
|
||||
// if hide_after=1, MinimizeToTray's AFTER the keystrokes land.
|
||||
// Hiding before SendInput would tip the Win10/11 anti-focus-
|
||||
// stealing rules into refusing to hand focus to the target.
|
||||
autofillPendingToast = entryDisplayName(entry) +
|
||||
(u ? ' · username + password sent' : ' · password sent');
|
||||
if (Bridge.active) Bridge.executeAutofill(u, pwd, quickSearchHideAfter);
|
||||
toast(entryDisplayName(entry) +
|
||||
(u ? ' · username + password sent' : ' · password sent'));
|
||||
}
|
||||
// Flags consumed — closeQuickSearchModal must not re-trigger.
|
||||
quickSearchFillMode = false;
|
||||
|
||||
Reference in New Issue
Block a user