1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-10 21:33:27 +00:00

[AC-2248][PM-5352] Bugfix - Fix non-working policy state in autofill settings service (#8156)

* fix broken policy state in autofill settings service

* cleanup and re-org

* move toast display tracking value and update to autofill settings state
This commit is contained in:
Jonathan Prusik
2024-03-06 16:07:46 -05:00
committed by GitHub
parent 356a15535c
commit c52456cbb6
30 changed files with 175 additions and 174 deletions

View File

@@ -0,0 +1,58 @@
export const TYPE_CHECK = {
FUNCTION: "function",
NUMBER: "number",
STRING: "string",
} as const;
export const EVENTS = {
CHANGE: "change",
INPUT: "input",
KEYDOWN: "keydown",
KEYPRESS: "keypress",
KEYUP: "keyup",
BLUR: "blur",
CLICK: "click",
FOCUS: "focus",
SCROLL: "scroll",
RESIZE: "resize",
DOMCONTENTLOADED: "DOMContentLoaded",
LOAD: "load",
MESSAGE: "message",
VISIBILITYCHANGE: "visibilitychange",
FOCUSOUT: "focusout",
} as const;
export const ClearClipboardDelay = {
Never: null as null,
TenSeconds: 10,
TwentySeconds: 20,
ThirtySeconds: 30,
OneMinute: 60,
TwoMinutes: 120,
FiveMinutes: 300,
} as const;
/* Context Menu item Ids */
export const AUTOFILL_CARD_ID = "autofill-card";
export const AUTOFILL_ID = "autofill";
export const SHOW_AUTOFILL_BUTTON = "show-autofill-button";
export const AUTOFILL_IDENTITY_ID = "autofill-identity";
export const COPY_IDENTIFIER_ID = "copy-identifier";
export const COPY_PASSWORD_ID = "copy-password";
export const COPY_USERNAME_ID = "copy-username";
export const COPY_VERIFICATION_CODE_ID = "copy-totp";
export const CREATE_CARD_ID = "create-card";
export const CREATE_IDENTITY_ID = "create-identity";
export const CREATE_LOGIN_ID = "create-login";
export const GENERATE_PASSWORD_ID = "generate-password";
export const NOOP_COMMAND_SUFFIX = "noop";
export const ROOT_ID = "root";
export const SEPARATOR_ID = "separator";
export const NOTIFICATION_BAR_LIFESPAN_MS = 150000; // 150 seconds
export const AutofillOverlayVisibility = {
Off: 0,
OnButtonClick: 1,
OnFieldFocus: 2,
} as const;

View File

@@ -1,16 +1,7 @@
import { filter, switchMap, tap, firstValueFrom, map, Observable } from "rxjs";
import { map, Observable } from "rxjs";
import {
ClearClipboardDelaySetting,
ClearClipboardDelay,
} from "../../../../../apps/browser/src/autofill/constants";
import {
AutofillOverlayVisibility,
InlineMenuVisibilitySetting,
} from "../../../../../apps/browser/src/autofill/utils/autofill-overlay.enum";
import { PolicyService } from "../../admin-console/abstractions/policy/policy.service.abstraction";
import { PolicyType } from "../../admin-console/enums/index";
import { Policy } from "../../admin-console/models/domain/policy";
import { PolicyType } from "../../admin-console/enums";
import {
AUTOFILL_SETTINGS_DISK,
AUTOFILL_SETTINGS_DISK_LOCAL,
@@ -19,6 +10,8 @@ import {
KeyDefinition,
StateProvider,
} from "../../platform/state";
import { ClearClipboardDelay, AutofillOverlayVisibility } from "../constants";
import { ClearClipboardDelaySetting, InlineMenuVisibilitySetting } from "../types";
const AUTOFILL_ON_PAGE_LOAD = new KeyDefinition(AUTOFILL_SETTINGS_DISK, "autofillOnPageLoad", {
deserializer: (value: boolean) => value ?? false,
@@ -32,10 +25,6 @@ const AUTOFILL_ON_PAGE_LOAD_DEFAULT = new KeyDefinition(
},
);
const AUTO_COPY_TOTP = new KeyDefinition(AUTOFILL_SETTINGS_DISK, "autoCopyTotp", {
deserializer: (value: boolean) => value ?? false,
});
const AUTOFILL_ON_PAGE_LOAD_CALLOUT_DISMISSED = new KeyDefinition(
AUTOFILL_SETTINGS_DISK,
"autofillOnPageLoadCalloutIsDismissed",
@@ -44,14 +33,18 @@ const AUTOFILL_ON_PAGE_LOAD_CALLOUT_DISMISSED = new KeyDefinition(
},
);
const ACTIVATE_AUTOFILL_ON_PAGE_LOAD_FROM_POLICY = new KeyDefinition(
AUTOFILL_SETTINGS_DISK_LOCAL,
"activateAutofillOnPageLoadFromPolicy",
const AUTOFILL_ON_PAGE_LOAD_POLICY_TOAST_HAS_DISPLAYED = new KeyDefinition(
AUTOFILL_SETTINGS_DISK,
"autofillOnPageLoadPolicyToastHasDisplayed",
{
deserializer: (value: boolean) => value ?? false,
},
);
const AUTO_COPY_TOTP = new KeyDefinition(AUTOFILL_SETTINGS_DISK, "autoCopyTotp", {
deserializer: (value: boolean) => value ?? false,
});
const INLINE_MENU_VISIBILITY = new KeyDefinition(
AUTOFILL_SETTINGS_DISK_LOCAL,
"inlineMenuVisibility",
@@ -73,17 +66,17 @@ export abstract class AutofillSettingsServiceAbstraction {
setAutofillOnPageLoad: (newValue: boolean) => Promise<void>;
autofillOnPageLoadDefault$: Observable<boolean>;
setAutofillOnPageLoadDefault: (newValue: boolean) => Promise<void>;
autoCopyTotp$: Observable<boolean>;
setAutoCopyTotp: (newValue: boolean) => Promise<void>;
autofillOnPageLoadCalloutIsDismissed$: Observable<boolean>;
setAutofillOnPageLoadCalloutIsDismissed: (newValue: boolean) => Promise<void>;
activateAutofillOnPageLoadFromPolicy$: Observable<boolean>;
setActivateAutofillOnPageLoadFromPolicy: (newValue: boolean) => Promise<void>;
setAutofillOnPageLoadPolicyToastHasDisplayed: (newValue: boolean) => Promise<void>;
autofillOnPageLoadPolicyToastHasDisplayed$: Observable<boolean>;
autoCopyTotp$: Observable<boolean>;
setAutoCopyTotp: (newValue: boolean) => Promise<void>;
inlineMenuVisibility$: Observable<InlineMenuVisibilitySetting>;
setInlineMenuVisibility: (newValue: InlineMenuVisibilitySetting) => Promise<void>;
clearClipboardDelay$: Observable<ClearClipboardDelaySetting>;
setClearClipboardDelay: (newValue: ClearClipboardDelaySetting) => Promise<void>;
handleActivateAutofillPolicy: (policies: Observable<Policy[]>) => Observable<boolean[]>;
}
export class AutofillSettingsService implements AutofillSettingsServiceAbstraction {
@@ -93,15 +86,17 @@ export class AutofillSettingsService implements AutofillSettingsServiceAbstracti
private autofillOnPageLoadDefaultState: ActiveUserState<boolean>;
readonly autofillOnPageLoadDefault$: Observable<boolean>;
private autoCopyTotpState: ActiveUserState<boolean>;
readonly autoCopyTotp$: Observable<boolean>;
private autofillOnPageLoadCalloutIsDismissedState: ActiveUserState<boolean>;
readonly autofillOnPageLoadCalloutIsDismissed$: Observable<boolean>;
private activateAutofillOnPageLoadFromPolicyState: ActiveUserState<boolean>;
readonly activateAutofillOnPageLoadFromPolicy$: Observable<boolean>;
private autofillOnPageLoadPolicyToastHasDisplayedState: ActiveUserState<boolean>;
readonly autofillOnPageLoadPolicyToastHasDisplayed$: Observable<boolean>;
private autoCopyTotpState: ActiveUserState<boolean>;
readonly autoCopyTotp$: Observable<boolean>;
private inlineMenuVisibilityState: GlobalState<InlineMenuVisibilitySetting>;
readonly inlineMenuVisibility$: Observable<InlineMenuVisibilitySetting>;
@@ -110,7 +105,7 @@ export class AutofillSettingsService implements AutofillSettingsServiceAbstracti
constructor(
private stateProvider: StateProvider,
policyService: PolicyService,
private policyService: PolicyService,
) {
this.autofillOnPageLoadState = this.stateProvider.getActive(AUTOFILL_ON_PAGE_LOAD);
this.autofillOnPageLoad$ = this.autofillOnPageLoadState.state$.pipe(map((x) => x ?? false));
@@ -122,20 +117,25 @@ export class AutofillSettingsService implements AutofillSettingsServiceAbstracti
map((x) => x ?? true),
);
this.autoCopyTotpState = this.stateProvider.getActive(AUTO_COPY_TOTP);
this.autoCopyTotp$ = this.autoCopyTotpState.state$.pipe(map((x) => x ?? false));
this.autofillOnPageLoadCalloutIsDismissedState = this.stateProvider.getActive(
AUTOFILL_ON_PAGE_LOAD_CALLOUT_DISMISSED,
);
this.autofillOnPageLoadCalloutIsDismissed$ =
this.autofillOnPageLoadCalloutIsDismissedState.state$.pipe(map((x) => x ?? false));
this.activateAutofillOnPageLoadFromPolicyState = this.stateProvider.getActive(
ACTIVATE_AUTOFILL_ON_PAGE_LOAD_FROM_POLICY,
this.activateAutofillOnPageLoadFromPolicy$ = this.policyService.policyAppliesToActiveUser$(
PolicyType.ActivateAutofill,
);
this.activateAutofillOnPageLoadFromPolicy$ =
this.activateAutofillOnPageLoadFromPolicyState.state$.pipe(map((x) => x ?? false));
this.autofillOnPageLoadPolicyToastHasDisplayedState = this.stateProvider.getActive(
AUTOFILL_ON_PAGE_LOAD_POLICY_TOAST_HAS_DISPLAYED,
);
this.autofillOnPageLoadPolicyToastHasDisplayed$ = this.autofillOnPageLoadState.state$.pipe(
map((x) => x ?? false),
);
this.autoCopyTotpState = this.stateProvider.getActive(AUTO_COPY_TOTP);
this.autoCopyTotp$ = this.autoCopyTotpState.state$.pipe(map((x) => x ?? false));
this.inlineMenuVisibilityState = this.stateProvider.getGlobal(INLINE_MENU_VISIBILITY);
this.inlineMenuVisibility$ = this.inlineMenuVisibilityState.state$.pipe(
@@ -146,8 +146,6 @@ export class AutofillSettingsService implements AutofillSettingsServiceAbstracti
this.clearClipboardDelay$ = this.clearClipboardDelayState.state$.pipe(
map((x) => x ?? ClearClipboardDelay.Never),
);
policyService.policies$.pipe(this.handleActivateAutofillPolicy.bind(this)).subscribe();
}
async setAutofillOnPageLoad(newValue: boolean): Promise<void> {
@@ -158,16 +156,16 @@ export class AutofillSettingsService implements AutofillSettingsServiceAbstracti
await this.autofillOnPageLoadDefaultState.update(() => newValue);
}
async setAutoCopyTotp(newValue: boolean): Promise<void> {
await this.autoCopyTotpState.update(() => newValue);
}
async setAutofillOnPageLoadCalloutIsDismissed(newValue: boolean): Promise<void> {
await this.autofillOnPageLoadCalloutIsDismissedState.update(() => newValue);
}
async setActivateAutofillOnPageLoadFromPolicy(newValue: boolean): Promise<void> {
await this.activateAutofillOnPageLoadFromPolicyState.update(() => newValue);
async setAutofillOnPageLoadPolicyToastHasDisplayed(newValue: boolean): Promise<void> {
await this.autofillOnPageLoadPolicyToastHasDisplayedState.update(() => newValue);
}
async setAutoCopyTotp(newValue: boolean): Promise<void> {
await this.autoCopyTotpState.update(() => newValue);
}
async setInlineMenuVisibility(newValue: InlineMenuVisibilitySetting): Promise<void> {
@@ -177,24 +175,4 @@ export class AutofillSettingsService implements AutofillSettingsServiceAbstracti
async setClearClipboardDelay(newValue: ClearClipboardDelaySetting): Promise<void> {
await this.clearClipboardDelayState.update(() => newValue);
}
/**
* If the ActivateAutofill policy is enabled, save a flag indicating if we need to
* enable Autofill on page load.
*/
handleActivateAutofillPolicy(policies$: Observable<Policy[]>): Observable<boolean[]> {
return policies$.pipe(
map((policies) => policies.find((p) => p.type == PolicyType.ActivateAutofill && p.enabled)),
filter((p) => p != null),
switchMap(async (_) => [
await firstValueFrom(this.activateAutofillOnPageLoadFromPolicy$),
await firstValueFrom(this.autofillOnPageLoad$),
]),
tap(([activated, autofillEnabled]) => {
if (activated === undefined) {
void this.setActivateAutofillOnPageLoadFromPolicy(!autofillEnabled);
}
}),
);
}
}

View File

@@ -0,0 +1,7 @@
import { ClearClipboardDelay, AutofillOverlayVisibility } from "../constants";
export type ClearClipboardDelaySetting =
(typeof ClearClipboardDelay)[keyof typeof ClearClipboardDelay];
export type InlineMenuVisibilitySetting =
(typeof AutofillOverlayVisibility)[keyof typeof AutofillOverlayVisibility];

View File

@@ -1,7 +1,15 @@
import { InlineMenuVisibilitySetting } from "../../../../../apps/browser/src/autofill/utils/autofill-overlay.enum";
import { StateDefinitionLike, MigrationHelper } from "../migration-helper";
import { Migrator } from "../migrator";
const AutofillOverlayVisibility = {
Off: 0,
OnButtonClick: 1,
OnFieldFocus: 2,
} as const;
type InlineMenuVisibilitySetting =
(typeof AutofillOverlayVisibility)[keyof typeof AutofillOverlayVisibility];
type ExpectedAccountState = {
settings?: {
autoFillOnPageLoadDefault?: boolean;

View File

@@ -1,7 +1,18 @@
import { ClearClipboardDelaySetting } from "../../../../../apps/browser/src/autofill/constants";
import { StateDefinitionLike, MigrationHelper } from "../migration-helper";
import { Migrator } from "../migrator";
const ClearClipboardDelay = {
Never: null as null,
TenSeconds: 10,
TwentySeconds: 20,
ThirtySeconds: 30,
OneMinute: 60,
TwoMinutes: 120,
FiveMinutes: 300,
} as const;
type ClearClipboardDelaySetting = (typeof ClearClipboardDelay)[keyof typeof ClearClipboardDelay];
type ExpectedAccountState = {
settings?: {
clearClipboard?: ClearClipboardDelaySetting;