[PM-5439] TOTP to clipboard does not work with autofill overlay (#7427)

* [PM-5439] TOTP to Clipboard Does not Work with Autofill Overlay

* [PM-5439] Adding jest tests to validate totp copy action when filling using the overlay
This commit is contained in:
Cesar Gonzalez 2024-01-09 11:23:00 -06:00 committed by GitHub
parent 0b3b039eaa
commit b144f5bce7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 1 deletions

View File

@ -12,6 +12,7 @@ import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { CipherService } from "@bitwarden/common/vault/services/cipher.service"; import { CipherService } from "@bitwarden/common/vault/services/cipher.service";
import { BrowserApi } from "../../platform/browser/browser-api"; import { BrowserApi } from "../../platform/browser/browser-api";
import BrowserPlatformUtilsService from "../../platform/services/browser-platform-utils.service";
import { BrowserStateService } from "../../platform/services/browser-state.service"; import { BrowserStateService } from "../../platform/services/browser-state.service";
import { SHOW_AUTOFILL_BUTTON } from "../constants"; import { SHOW_AUTOFILL_BUTTON } from "../constants";
import { import {
@ -47,6 +48,7 @@ describe("OverlayBackground", () => {
const settingsService = mock<SettingsService>(); const settingsService = mock<SettingsService>();
const stateService = mock<BrowserStateService>(); const stateService = mock<BrowserStateService>();
const i18nService = mock<I18nService>(); const i18nService = mock<I18nService>();
const platformUtilsService = mock<BrowserPlatformUtilsService>();
const initOverlayElementPorts = (options = { initList: true, initButton: true }) => { const initOverlayElementPorts = (options = { initList: true, initButton: true }) => {
const { initList, initButton } = options; const { initList, initButton } = options;
if (initButton) { if (initButton) {
@ -71,6 +73,7 @@ describe("OverlayBackground", () => {
settingsService, settingsService,
stateService, stateService,
i18nService, i18nService,
platformUtilsService,
); );
overlayBackground.init(); overlayBackground.init();
}); });
@ -1263,6 +1266,24 @@ describe("OverlayBackground", () => {
]).entries(), ]).entries(),
); );
}); });
it("copies the cipher's totp code to the clipboard after filling", async () => {
const cipher1 = mock<CipherView>({ id: "overlay-cipher-1" });
overlayBackground["overlayLoginCiphers"] = new Map([["overlay-cipher-1", cipher1]]);
isPasswordRepromptRequiredSpy.mockResolvedValue(false);
const copyToClipboardSpy = jest
.spyOn(overlayBackground["platformUtilsService"], "copyToClipboard")
.mockImplementation();
doAutoFillSpy.mockReturnValueOnce("totp-code");
sendPortMessage(listPortSpy, {
command: "fillSelectedListItem",
overlayCipherId: "overlay-cipher-2",
});
await flushPromises();
expect(copyToClipboardSpy).toHaveBeenCalledWith("totp-code", { window });
});
}); });
describe("getNewVaultItemDetails", () => { describe("getNewVaultItemDetails", () => {

View File

@ -3,6 +3,7 @@ import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { ThemeType } from "@bitwarden/common/platform/enums"; import { ThemeType } from "@bitwarden/common/platform/enums";
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
@ -91,6 +92,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
private settingsService: SettingsService, private settingsService: SettingsService,
private stateService: StateService, private stateService: StateService,
private i18nService: I18nService, private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService,
) { ) {
this.iconsServerUrl = this.environmentService.getIconsUrl(); this.iconsServerUrl = this.environmentService.getIconsUrl();
} }
@ -227,7 +229,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
if (await this.autofillService.isPasswordRepromptRequired(cipher, sender.tab)) { if (await this.autofillService.isPasswordRepromptRequired(cipher, sender.tab)) {
return; return;
} }
await this.autofillService.doAutoFill({ const totpCode = await this.autofillService.doAutoFill({
tab: sender.tab, tab: sender.tab,
cipher: cipher, cipher: cipher,
pageDetails: this.pageDetailsForTab[sender.tab.id], pageDetails: this.pageDetailsForTab[sender.tab.id],
@ -235,6 +237,10 @@ class OverlayBackground implements OverlayBackgroundInterface {
allowTotpAutofill: true, allowTotpAutofill: true,
}); });
if (totpCode) {
this.platformUtilsService.copyToClipboard(totpCode, { window });
}
this.overlayLoginCiphers = new Map([[overlayCipherId, cipher], ...this.overlayLoginCiphers]); this.overlayLoginCiphers = new Map([[overlayCipherId, cipher], ...this.overlayLoginCiphers]);
} }

View File

@ -728,6 +728,7 @@ export default class MainBackground {
this.settingsService, this.settingsService,
this.stateService, this.stateService,
this.i18nService, this.i18nService,
this.platformUtilsService,
); );
this.filelessImporterBackground = new FilelessImporterBackground( this.filelessImporterBackground = new FilelessImporterBackground(
this.configService, this.configService,