From 1b3bc71e5061dbc2855aa219f84e15c0028377ec Mon Sep 17 00:00:00 2001 From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com> Date: Tue, 4 Feb 2025 12:38:14 -0800 Subject: [PATCH] [PM-15943] - fix extension flicker when filling in a password (#13143) * update lastUsedDate in background script * fix tests --- .../src/autofill/services/autofill.service.spec.ts | 11 +++++++---- .../browser/src/autofill/services/autofill.service.ts | 7 ++++++- apps/browser/src/background/main.background.ts | 1 + apps/browser/src/background/runtime.background.ts | 5 +++++ 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/apps/browser/src/autofill/services/autofill.service.spec.ts b/apps/browser/src/autofill/services/autofill.service.spec.ts index 16b11b98866..378521cfc42 100644 --- a/apps/browser/src/autofill/services/autofill.service.spec.ts +++ b/apps/browser/src/autofill/services/autofill.service.spec.ts @@ -747,7 +747,7 @@ describe("AutofillService", () => { jest.spyOn(autofillService as any, "generateFillScript"); jest.spyOn(autofillService as any, "generateLoginFillScript"); jest.spyOn(logService, "info"); - jest.spyOn(cipherService, "updateLastUsedDate"); + jest.spyOn(chrome.runtime, "sendMessage"); jest.spyOn(eventCollectionService, "collect"); const autofillResult = await autofillService.doAutoFill(autofillOptions); @@ -769,7 +769,10 @@ describe("AutofillService", () => { ); expect(autofillService["generateLoginFillScript"]).toHaveBeenCalled(); expect(logService.info).not.toHaveBeenCalled(); - expect(cipherService.updateLastUsedDate).toHaveBeenCalledWith(autofillOptions.cipher.id); + expect(chrome.runtime.sendMessage).toHaveBeenCalledWith({ + cipherId: autofillOptions.cipher.id, + command: "updateLastUsedDate", + }); expect(chrome.tabs.sendMessage).toHaveBeenCalledWith( autofillOptions.pageDetails[0].tab.id, { @@ -890,11 +893,11 @@ describe("AutofillService", () => { it("skips updating the cipher's last used date if the passed options indicate that we should skip the last used cipher", async () => { autofillOptions.skipLastUsed = true; - jest.spyOn(cipherService, "updateLastUsedDate"); + jest.spyOn(chrome.runtime, "sendMessage"); await autofillService.doAutoFill(autofillOptions); - expect(cipherService.updateLastUsedDate).not.toHaveBeenCalled(); + expect(chrome.runtime.sendMessage).not.toHaveBeenCalled(); }); it("returns early if the fillScript cannot be generated", async () => { diff --git a/apps/browser/src/autofill/services/autofill.service.ts b/apps/browser/src/autofill/services/autofill.service.ts index 6d0e9954ade..c35b19990cb 100644 --- a/apps/browser/src/autofill/services/autofill.service.ts +++ b/apps/browser/src/autofill/services/autofill.service.ts @@ -463,8 +463,13 @@ export default class AutofillService implements AutofillServiceInterface { fillScript.properties.delay_between_operations = 20; didAutofill = true; + if (!options.skipLastUsed) { - await this.cipherService.updateLastUsedDate(options.cipher.id); + // In order to prevent a UI update send message to background script to update last used date + await chrome.runtime.sendMessage({ + command: "updateLastUsedDate", + cipherId: options.cipher.id, + }); } // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 73b5f783b3f..49a29ab8581 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -1142,6 +1142,7 @@ export default class MainBackground { this.accountService, lockService, this.billingAccountProfileStateService, + this.cipherService, ); this.nativeMessagingBackground = new NativeMessagingBackground( this.keyService, diff --git a/apps/browser/src/background/runtime.background.ts b/apps/browser/src/background/runtime.background.ts index 2a756293070..b9622e82005 100644 --- a/apps/browser/src/background/runtime.background.ts +++ b/apps/browser/src/background/runtime.background.ts @@ -16,6 +16,7 @@ import { MessageListener, isExternalMessage } from "@bitwarden/common/platform/m import { devFlagEnabled } from "@bitwarden/common/platform/misc/flags"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { NotificationsService } from "@bitwarden/common/platform/notifications"; +import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherType } from "@bitwarden/common/vault/enums"; import { BiometricsCommands } from "@bitwarden/key-management"; @@ -53,6 +54,7 @@ export default class RuntimeBackground { private accountService: AccountService, private readonly lockService: LockService, private billingAccountProfileStateService: BillingAccountProfileStateService, + private cipherService: CipherService, ) { // onInstalled listener must be wired up before anything else, so we do it in the ctor chrome.runtime.onInstalled.addListener((details: any) => { @@ -200,6 +202,9 @@ export default class RuntimeBackground { case BiometricsCommands.GetBiometricsStatusForUser: { return await this.main.biometricsService.getBiometricsStatusForUser(msg.userId); } + case "updateLastUsedDate": { + return await this.cipherService.updateLastUsedDate(msg.cipherId); + } case "getUseTreeWalkerApiForPageDetailsCollectionFeatureFlag": { return await this.configService.getFeatureFlag( FeatureFlag.UseTreeWalkerApiForPageDetailsCollection,