1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-11 22:03:36 +00:00

“PM-15592 (#12489)

This commit is contained in:
Daniel Riera
2024-12-27 13:31:11 -05:00
committed by GitHub
parent 7837e08b23
commit 6d65ce9abd
4 changed files with 37 additions and 5 deletions

View File

@@ -21,8 +21,9 @@ describe("InlineMenuFieldQualificationService", () => {
}); });
describe("isFieldForLoginForm", () => { 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["inlineMenuTotpFeatureFlag"] = true;
inlineMenuFieldQualificationService["premiumEnabled"] = true;
const field = mock<AutofillField>({ const field = mock<AutofillField>({
type: "text", type: "text",
autoCompleteType: "one-time-code", 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"] = false;
inlineMenuFieldQualificationService["inlineMenuTotpFeatureFlag"] = true;
const field = mock<AutofillField>({
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<AutofillField>({ const field = mock<AutofillField>({
type: "text", type: "text",
autoCompleteType: "one-time-code", autoCompleteType: "one-time-code",

View File

@@ -151,14 +151,17 @@ export class InlineMenuFieldQualificationService
private totpFieldAutocompleteValue = "one-time-code"; private totpFieldAutocompleteValue = "one-time-code";
private inlineMenuFieldQualificationFlagSet = false; private inlineMenuFieldQualificationFlagSet = false;
private inlineMenuTotpFeatureFlag = false; private inlineMenuTotpFeatureFlag = false;
private premiumEnabled = false;
constructor() { constructor() {
void Promise.all([ void Promise.all([
sendExtensionMessage("getInlineMenuFieldQualificationFeatureFlag"), sendExtensionMessage("getInlineMenuFieldQualificationFeatureFlag"),
sendExtensionMessage("getInlineMenuTotpFeatureFlag"), sendExtensionMessage("getInlineMenuTotpFeatureFlag"),
]).then(([fieldQualificationFlag, totpFeatureFlag]) => { sendExtensionMessage("getUserPremiumStatus"),
]).then(([fieldQualificationFlag, totpFeatureFlag, premiumStatus]) => {
this.inlineMenuFieldQualificationFlagSet = !!fieldQualificationFlag?.result; this.inlineMenuFieldQualificationFlagSet = !!fieldQualificationFlag?.result;
this.inlineMenuTotpFeatureFlag = !!totpFeatureFlag?.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); const isTotpField = this.isTotpField(field);
// Autofill does not fill totp inputs with a "password" `type` attribute value
const passwordType = field.type === "password"; const passwordType = field.type === "password";
if (isTotpField && !passwordType) { if (isTotpField && !passwordType) {
return true; return true;

View File

@@ -1104,6 +1104,7 @@ export default class MainBackground {
messageListener, messageListener,
this.accountService, this.accountService,
lockService, lockService,
this.billingAccountProfileStateService,
); );
this.nativeMessagingBackground = new NativeMessagingBackground( this.nativeMessagingBackground = new NativeMessagingBackground(
this.keyService, this.keyService,

View File

@@ -7,6 +7,7 @@ import { NotificationsService } from "@bitwarden/common/abstractions/notificatio
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { AutofillOverlayVisibility, ExtensionCommand } from "@bitwarden/common/autofill/constants"; import { AutofillOverlayVisibility, ExtensionCommand } from "@bitwarden/common/autofill/constants";
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service"; 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 { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-management/abstractions/process-reload.service"; import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-management/abstractions/process-reload.service";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
@@ -50,6 +51,7 @@ export default class RuntimeBackground {
private messageListener: MessageListener, private messageListener: MessageListener,
private accountService: AccountService, private accountService: AccountService,
private readonly lockService: LockService, private readonly lockService: LockService,
private billingAccountProfileStateService: BillingAccountProfileStateService,
) { ) {
// onInstalled listener must be wired up before anything else, so we do it in the ctor // onInstalled listener must be wired up before anything else, so we do it in the ctor
chrome.runtime.onInstalled.addListener((details: any) => { chrome.runtime.onInstalled.addListener((details: any) => {
@@ -74,6 +76,7 @@ export default class RuntimeBackground {
"getUseTreeWalkerApiForPageDetailsCollectionFeatureFlag", "getUseTreeWalkerApiForPageDetailsCollectionFeatureFlag",
"getInlineMenuFieldQualificationFeatureFlag", "getInlineMenuFieldQualificationFeatureFlag",
"getInlineMenuTotpFeatureFlag", "getInlineMenuTotpFeatureFlag",
"getUserPremiumStatus",
]; ];
if (messagesWithResponse.includes(msg.command)) { if (messagesWithResponse.includes(msg.command)) {
@@ -198,6 +201,12 @@ export default class RuntimeBackground {
case "getInlineMenuFieldQualificationFeatureFlag": { case "getInlineMenuFieldQualificationFeatureFlag": {
return await this.configService.getFeatureFlag(FeatureFlag.InlineMenuFieldQualification); return await this.configService.getFeatureFlag(FeatureFlag.InlineMenuFieldQualification);
} }
case "getUserPremiumStatus": {
const result = await firstValueFrom(
this.billingAccountProfileStateService.hasPremiumFromAnySource$,
);
return result;
}
case "getInlineMenuTotpFeatureFlag": { case "getInlineMenuTotpFeatureFlag": {
return await this.configService.getFeatureFlag(FeatureFlag.InlineMenuTotp); return await this.configService.getFeatureFlag(FeatureFlag.InlineMenuTotp);
} }