fix(autofill): kill residual hotkey chord; dedicated fail-balloon setting
Residual new-entry trigger (1 in 6): password chars go out as KEYEVENTF_UNICODE (VK_PACKET, can't match a hotkey) — the real chord risk is the Ctrl+A clear-field, which sends a real VK_A. If the user re-presses Ctrl+Shift mid-sequence, that VK_A becomes physical Ctrl+Shift+A = our own new-entry hotkey. ForceReleaseModifiers now runs inside SendSelectAllAndDelete, at the risky instant, not just once up front. Balloon: was gated by "Show tray notifications" (OFF for this user) — now gated by its own synced setting "Tray alert when autofill is blocked" (autofillFailBalloon, Settings > Autofill, default ON), carried as notify=0 on cmd://autofill/execute. ShowBalloon no longer gates internally; each caller applies its own setting. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -108,6 +108,9 @@ type
|
||||
// Send Ctrl+A + Del before typing each field (user setting, default ON;
|
||||
// OFF for targets where Ctrl+A isn't select-all — terminals, RDP).
|
||||
FAutofillPendingClear: Boolean;
|
||||
// Tray balloon when the fill fails while the window is hidden (user
|
||||
// setting "Tray alert when autofill is blocked", default ON).
|
||||
FAutofillPendingNotify: Boolean;
|
||||
// Created dynamically in FormCreate so the directive can pick either
|
||||
// TTMSFNCWebBrowser or TTMSFNCEdgeWebBrowser at compile time without
|
||||
// needing two .fmx variants. Aligned to Client to fill the remaining
|
||||
@@ -900,7 +903,8 @@ begin
|
||||
FAutofillPendingHWND := FAutofillTargetHWND;
|
||||
FAutofillPendingHide := GetParam('hide_after') = '1';
|
||||
FAutofillPendingUserOnly := GetParam('field') = 'user';
|
||||
FAutofillPendingClear := GetParam('clear') <> '0'; // absent = ON
|
||||
FAutofillPendingClear := GetParam('clear') <> '0'; // absent = ON
|
||||
FAutofillPendingNotify := GetParam('notify') <> '0'; // absent = ON
|
||||
FAutofillTargetHWND := 0;
|
||||
|
||||
// Small timer so SetForegroundWindow has time to take effect before
|
||||
@@ -1453,7 +1457,7 @@ procedure TMainForm.AutofillTimerTick(Sender: TObject);
|
||||
var
|
||||
TargetHwnd: HWND;
|
||||
PendingUser, PendingPass: string;
|
||||
HideAfter, UserOnly, ClearFirst: Boolean;
|
||||
HideAfter, UserOnly, ClearFirst, NotifyFail: Boolean;
|
||||
ForegroundAfter: HWND;
|
||||
begin
|
||||
TargetHwnd := FAutofillPendingHWND;
|
||||
@@ -1462,12 +1466,14 @@ begin
|
||||
HideAfter := FAutofillPendingHide;
|
||||
UserOnly := FAutofillPendingUserOnly;
|
||||
ClearFirst := FAutofillPendingClear;
|
||||
NotifyFail := FAutofillPendingNotify;
|
||||
FAutofillPendingHWND := 0;
|
||||
FAutofillPendingUser := '';
|
||||
FAutofillPendingPass := '';
|
||||
FAutofillPendingHide := False;
|
||||
FAutofillPendingUserOnly := False;
|
||||
FAutofillPendingClear := False;
|
||||
FAutofillPendingNotify := False;
|
||||
|
||||
TTimer(Sender).Enabled := False;
|
||||
TTimer(Sender).Free;
|
||||
@@ -1487,9 +1493,9 @@ begin
|
||||
'if(window.Bridge&&typeof Bridge.onAutofillResult==="function")' +
|
||||
'Bridge.onAutofillResult(' + BoolToStr(LFillOk, True).ToLower + ')');
|
||||
// Window hidden (tray) → the in-app failure toast is invisible; surface
|
||||
// the block via a tray balloon instead (gated by the tray-notifications
|
||||
// setting inside ShowBalloon).
|
||||
if (not LFillOk) and
|
||||
// the block via a tray balloon instead (gated by the dedicated
|
||||
// "Tray alert when autofill is blocked" setting, default ON).
|
||||
if (not LFillOk) and NotifyFail and
|
||||
((not Self.Visible) or IsIconic(WindowHandleToPlatform(Self.Handle).Wnd)) then
|
||||
FBridge.ShowBalloon('Autofill blocked',
|
||||
'The target window runs as administrator — Windows silently blocks ' +
|
||||
|
||||
Reference in New Issue
Block a user