From 6d65ce9abd32c758610fa04c0fca1c11f4bf7379 Mon Sep 17 00:00:00 2001 From: Daniel Riera Date: Fri, 27 Dec 2024 13:31:11 -0500 Subject: [PATCH] =?UTF-8?q?=E2=80=9CPM-15592=20(#12489)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...e-menu-field-qualification.service.spec.ts | 22 +++++++++++++++++-- ...inline-menu-field-qualification.service.ts | 10 ++++++--- .../browser/src/background/main.background.ts | 1 + .../src/background/runtime.background.ts | 9 ++++++++ 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/apps/browser/src/autofill/services/inline-menu-field-qualification.service.spec.ts b/apps/browser/src/autofill/services/inline-menu-field-qualification.service.spec.ts index 6e267e25c3f..dc59e05a18b 100644 --- a/apps/browser/src/autofill/services/inline-menu-field-qualification.service.spec.ts +++ b/apps/browser/src/autofill/services/inline-menu-field-qualification.service.spec.ts @@ -21,8 +21,9 @@ describe("InlineMenuFieldQualificationService", () => { }); describe("isFieldForLoginForm", () => { - it("does not disqualify totp fields with flag set to true", () => { + it("does not disqualify totp fields for premium users with flag set to true", () => { inlineMenuFieldQualificationService["inlineMenuTotpFeatureFlag"] = true; + inlineMenuFieldQualificationService["premiumEnabled"] = true; const field = mock({ type: "text", autoCompleteType: "one-time-code", @@ -36,8 +37,25 @@ describe("InlineMenuFieldQualificationService", () => { ); }); - it("disqualify totp fields with flag set to false", () => { + it("disqualifies totp fields for premium users with flag set to false", () => { inlineMenuFieldQualificationService["inlineMenuTotpFeatureFlag"] = false; + inlineMenuFieldQualificationService["inlineMenuTotpFeatureFlag"] = true; + const field = mock({ + type: "text", + autoCompleteType: "one-time-code", + htmlName: "totp", + htmlID: "totp", + placeholder: "totp", + }); + + expect(inlineMenuFieldQualificationService.isFieldForLoginForm(field, pageDetails)).toBe( + false, + ); + }); + + it("disqualifies totp fields for non-premium users with flag set to true", () => { + inlineMenuFieldQualificationService["inlineMenuTotpFeatureFlag"] = true; + inlineMenuFieldQualificationService["premiumEnabled"] = false; const field = mock({ type: "text", autoCompleteType: "one-time-code", diff --git a/apps/browser/src/autofill/services/inline-menu-field-qualification.service.ts b/apps/browser/src/autofill/services/inline-menu-field-qualification.service.ts index 32e55988a7a..43efd338c6e 100644 --- a/apps/browser/src/autofill/services/inline-menu-field-qualification.service.ts +++ b/apps/browser/src/autofill/services/inline-menu-field-qualification.service.ts @@ -151,14 +151,17 @@ export class InlineMenuFieldQualificationService private totpFieldAutocompleteValue = "one-time-code"; private inlineMenuFieldQualificationFlagSet = false; private inlineMenuTotpFeatureFlag = false; + private premiumEnabled = false; constructor() { void Promise.all([ sendExtensionMessage("getInlineMenuFieldQualificationFeatureFlag"), sendExtensionMessage("getInlineMenuTotpFeatureFlag"), - ]).then(([fieldQualificationFlag, totpFeatureFlag]) => { + sendExtensionMessage("getUserPremiumStatus"), + ]).then(([fieldQualificationFlag, totpFeatureFlag, premiumStatus]) => { this.inlineMenuFieldQualificationFlagSet = !!fieldQualificationFlag?.result; this.inlineMenuTotpFeatureFlag = !!totpFeatureFlag?.result; + this.premiumEnabled = !!premiumStatus?.result; }); } @@ -174,10 +177,11 @@ export class InlineMenuFieldQualificationService } /** - * Autofill does not fill password type totp input fields + * Totp inline menu is available only for premium users. */ - if (this.inlineMenuTotpFeatureFlag) { + if (this.inlineMenuTotpFeatureFlag && this.premiumEnabled) { const isTotpField = this.isTotpField(field); + // Autofill does not fill totp inputs with a "password" `type` attribute value const passwordType = field.type === "password"; if (isTotpField && !passwordType) { return true; diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index aaee59ee3fa..555e3a13fa0 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -1104,6 +1104,7 @@ export default class MainBackground { messageListener, this.accountService, lockService, + this.billingAccountProfileStateService, ); 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 f91b6983a08..56ad7909e61 100644 --- a/apps/browser/src/background/runtime.background.ts +++ b/apps/browser/src/background/runtime.background.ts @@ -7,6 +7,7 @@ import { NotificationsService } from "@bitwarden/common/abstractions/notificatio import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { AutofillOverlayVisibility, ExtensionCommand } from "@bitwarden/common/autofill/constants"; import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service"; +import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-management/abstractions/process-reload.service"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; @@ -50,6 +51,7 @@ export default class RuntimeBackground { private messageListener: MessageListener, private accountService: AccountService, private readonly lockService: LockService, + private billingAccountProfileStateService: BillingAccountProfileStateService, ) { // onInstalled listener must be wired up before anything else, so we do it in the ctor chrome.runtime.onInstalled.addListener((details: any) => { @@ -74,6 +76,7 @@ export default class RuntimeBackground { "getUseTreeWalkerApiForPageDetailsCollectionFeatureFlag", "getInlineMenuFieldQualificationFeatureFlag", "getInlineMenuTotpFeatureFlag", + "getUserPremiumStatus", ]; if (messagesWithResponse.includes(msg.command)) { @@ -198,6 +201,12 @@ export default class RuntimeBackground { case "getInlineMenuFieldQualificationFeatureFlag": { return await this.configService.getFeatureFlag(FeatureFlag.InlineMenuFieldQualification); } + case "getUserPremiumStatus": { + const result = await firstValueFrom( + this.billingAccountProfileStateService.hasPremiumFromAnySource$, + ); + return result; + } case "getInlineMenuTotpFeatureFlag": { return await this.configService.getFeatureFlag(FeatureFlag.InlineMenuTotp); }