From 4bf90b0fb3834957bfdd7c997b65a519f9c39f3e Mon Sep 17 00:00:00 2001 From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:55:31 -0800 Subject: [PATCH] [PM-27754] - [Defect] MP prompt is missing before "Cannot autofill" modal when trying to autofill a login with "Exact" default matching set (#17247) * add persistent callout in settings for non-premium users * always call password reprompt in doAutofill * ensure password reprompt is checked in all instances * Revert "add persistent callout in settings for non-premium users" This reverts commit d206832cd3c91ce2366e55a60ff9255f4fc51f3f. --- .../item-more-options.component.spec.ts | 39 +++++++++++++------ .../item-more-options.component.ts | 8 ++-- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/apps/browser/src/vault/popup/components/vault-v2/item-more-options/item-more-options.component.spec.ts b/apps/browser/src/vault/popup/components/vault-v2/item-more-options/item-more-options.component.spec.ts index 5fcc4f78eb..5927da6c3d 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/item-more-options/item-more-options.component.spec.ts +++ b/apps/browser/src/vault/popup/components/vault-v2/item-more-options/item-more-options.component.spec.ts @@ -144,6 +144,15 @@ describe("ItemMoreOptionsComponent", () => { } describe("doAutofill", () => { + it("calls the passwordService to passwordRepromptCheck", async () => { + autofillSvc.currentAutofillTab$.next({ url: "https://page.example.com" }); + mockConfirmDialogResult(AutofillConfirmationDialogResult.AutofilledOnly); + + await component.doAutofill(); + + expect(passwordRepromptService.passwordRepromptCheck).toHaveBeenCalledWith(baseCipher); + }); + it("calls the autofill service to autofill without showing the confirmation dialog when the feature flag is disabled or search text is not present", async () => { autofillSvc.currentAutofillTab$.next({ url: "https://page.example.com" }); @@ -160,15 +169,6 @@ describe("ItemMoreOptionsComponent", () => { expect(dialogService.openSimpleDialog).not.toHaveBeenCalled(); }); - it("calls the passwordService to passwordRepromptCheck", async () => { - autofillSvc.currentAutofillTab$.next({ url: "https://page.example.com" }); - mockConfirmDialogResult(AutofillConfirmationDialogResult.AutofilledOnly); - - await component.doAutofill(); - - expect(passwordRepromptService.passwordRepromptCheck).toHaveBeenCalledWith(baseCipher); - }); - it("does nothing if the user fails master password reprompt", async () => { baseCipher.reprompt = 2; // Master Password reprompt enabled autofillSvc.currentAutofillTab$.next({ url: "https://page.example.com" }); @@ -199,6 +199,15 @@ describe("ItemMoreOptionsComponent", () => { passwordRepromptService.passwordRepromptCheck.mockResolvedValue(true); }); + it("calls the passwordService to passwordRepromptCheck", async () => { + autofillSvc.currentAutofillTab$.next({ url: "https://page.example.com" }); + mockConfirmDialogResult(AutofillConfirmationDialogResult.AutofilledOnly); + + await component.doAutofill(); + + expect(passwordRepromptService.passwordRepromptCheck).toHaveBeenCalledWith(baseCipher); + }); + it("opens the autofill confirmation dialog with filtered saved URLs when the feature flag is enabled and search text is present", async () => { autofillSvc.currentAutofillTab$.next({ url: "https://page.example.com/path" }); const openSpy = mockConfirmDialogResult(AutofillConfirmationDialogResult.Canceled); @@ -259,7 +268,16 @@ describe("ItemMoreOptionsComponent", () => { uriMatchStrategy$.next(UriMatchStrategy.Exact); }); - it("shows the exact match dialog and not the password dialog", async () => { + it("calls the passwordService to passwordRepromptCheck", async () => { + autofillSvc.currentAutofillTab$.next({ url: "https://page.example.com" }); + mockConfirmDialogResult(AutofillConfirmationDialogResult.AutofilledOnly); + + await component.doAutofill(); + + expect(passwordRepromptService.passwordRepromptCheck).toHaveBeenCalledWith(baseCipher); + }); + + it("shows the exact match dialog", async () => { autofillSvc.currentAutofillTab$.next({ url: "https://no-match.example.com" }); await component.doAutofill(); @@ -273,7 +291,6 @@ describe("ItemMoreOptionsComponent", () => { }), ); expect(autofillSvc.doAutofill).not.toHaveBeenCalled(); - expect(passwordRepromptService.passwordRepromptCheck).not.toHaveBeenCalled(); expect(autofillSvc.doAutofillAndSave).not.toHaveBeenCalled(); }); }); diff --git a/apps/browser/src/vault/popup/components/vault-v2/item-more-options/item-more-options.component.ts b/apps/browser/src/vault/popup/components/vault-v2/item-more-options/item-more-options.component.ts index dcdc558362..1316a0d32b 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/item-more-options/item-more-options.component.ts +++ b/apps/browser/src/vault/popup/components/vault-v2/item-more-options/item-more-options.component.ts @@ -202,6 +202,10 @@ export class ItemMoreOptionsComponent { async doAutofill() { const cipher = await this.cipherService.getFullCipherView(this.cipher); + if (!(await this.passwordRepromptService.passwordRepromptCheck(this.cipher))) { + return; + } + const uris = cipher.login?.uris ?? []; const cipherHasAllExactMatchLoginUris = uris.length > 0 && uris.every((u) => u.uri && u.match === UriMatchStrategy.Exact); @@ -223,10 +227,6 @@ export class ItemMoreOptionsComponent { return; } - if (!(await this.passwordRepromptService.passwordRepromptCheck(this.cipher))) { - return; - } - if (!showAutofillConfirmation) { await this.vaultPopupAutofillService.doAutofill(cipher, true, true); return;