mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 22:03:36 +00:00
[PM-22783] Add Feature Flag, Settings Toggle, and Services for Autotype MVP (#15262)
* [PM-22783] Add initial feature flag and settings toggle for autotype MVP * [PM-22783] Undo Cargo.lock changes * [PM-22783] Disable console.log block * [PM-22783] Lint fix * [PM-22783] Small updates * [PM-22783] Build fix * [PM-22783] Use combineLatest in updating the desktop autotype service * [PM-22783] Check if the user is on Windows * [PM-22783] Undo access selector html change, linting keeps removing this * [PM-22783] Fix failing test * [PM-22783] Update autotypeEnabled to be stored in service * [PM-22783] Add todo comments * [PM-22783] Add SlimConfigService and MainDesktopAutotypeService * [PM-22783] Small fixes
This commit is contained in:
@@ -489,6 +489,22 @@
|
|||||||
"enableDuckDuckGoBrowserIntegrationDesc" | i18n
|
"enableDuckDuckGoBrowserIntegrationDesc" | i18n
|
||||||
}}</small>
|
}}</small>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group" *ngIf="showEnableAutotype">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label for="enableAutotype">
|
||||||
|
<input
|
||||||
|
id="enableAutotype"
|
||||||
|
type="checkbox"
|
||||||
|
formControlName="enableAutotype"
|
||||||
|
(change)="saveEnableAutotype()"
|
||||||
|
/>
|
||||||
|
{{ "enableAutotype" | i18n }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<small class="help-block"
|
||||||
|
><b>{{ "important" | i18n }}</b> {{ "enableAutotypeDescription" | i18n }}</small
|
||||||
|
>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="theme">{{ "theme" | i18n }}</label>
|
<label for="theme">{{ "theme" | i18n }}</label>
|
||||||
<select
|
<select
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import { BiometricStateService, BiometricsStatus, KeyService } from "@bitwarden/
|
|||||||
import { SetPinComponent } from "../../auth/components/set-pin.component";
|
import { SetPinComponent } from "../../auth/components/set-pin.component";
|
||||||
import { SshAgentPromptType } from "../../autofill/models/ssh-agent-setting";
|
import { SshAgentPromptType } from "../../autofill/models/ssh-agent-setting";
|
||||||
import { DesktopAutofillSettingsService } from "../../autofill/services/desktop-autofill-settings.service";
|
import { DesktopAutofillSettingsService } from "../../autofill/services/desktop-autofill-settings.service";
|
||||||
|
import { DesktopAutotypeService } from "../../autofill/services/desktop-autotype.service";
|
||||||
import { DesktopBiometricsService } from "../../key-management/biometrics/desktop.biometrics.service";
|
import { DesktopBiometricsService } from "../../key-management/biometrics/desktop.biometrics.service";
|
||||||
import { DesktopSettingsService } from "../../platform/services/desktop-settings.service";
|
import { DesktopSettingsService } from "../../platform/services/desktop-settings.service";
|
||||||
import { NativeMessagingManifestService } from "../services/native-messaging-manifest.service";
|
import { NativeMessagingManifestService } from "../services/native-messaging-manifest.service";
|
||||||
@@ -69,6 +70,7 @@ describe("SettingsComponent", () => {
|
|||||||
const messagingService = mock<MessagingService>();
|
const messagingService = mock<MessagingService>();
|
||||||
const keyService = mock<KeyService>();
|
const keyService = mock<KeyService>();
|
||||||
const dialogService = mock<DialogService>();
|
const dialogService = mock<DialogService>();
|
||||||
|
const desktopAutotypeService = mock<DesktopAutotypeService>();
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
@@ -124,6 +126,7 @@ describe("SettingsComponent", () => {
|
|||||||
{ provide: VaultTimeoutSettingsService, useValue: vaultTimeoutSettingsService },
|
{ provide: VaultTimeoutSettingsService, useValue: vaultTimeoutSettingsService },
|
||||||
{ provide: ValidationService, useValue: validationService },
|
{ provide: ValidationService, useValue: validationService },
|
||||||
{ provide: MessagingService, useValue: messagingService },
|
{ provide: MessagingService, useValue: messagingService },
|
||||||
|
{ provide: DesktopAutotypeService, useValue: desktopAutotypeService },
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA],
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
@@ -160,6 +163,7 @@ describe("SettingsComponent", () => {
|
|||||||
themeStateService.selectedTheme$ = of(ThemeType.System);
|
themeStateService.selectedTheme$ = of(ThemeType.System);
|
||||||
i18nService.userSetLocale$ = of("en");
|
i18nService.userSetLocale$ = of("en");
|
||||||
pinServiceAbstraction.isPinSet.mockResolvedValue(false);
|
pinServiceAbstraction.isPinSet.mockResolvedValue(false);
|
||||||
|
desktopAutotypeService.autotypeEnabled$ = of(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
|||||||
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
||||||
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||||
import { DeviceType } from "@bitwarden/common/enums";
|
import { DeviceType } from "@bitwarden/common/enums";
|
||||||
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
import {
|
import {
|
||||||
VaultTimeout,
|
VaultTimeout,
|
||||||
VaultTimeoutAction,
|
VaultTimeoutAction,
|
||||||
@@ -48,6 +49,7 @@ import { KeyService, BiometricStateService, BiometricsStatus } from "@bitwarden/
|
|||||||
import { SetPinComponent } from "../../auth/components/set-pin.component";
|
import { SetPinComponent } from "../../auth/components/set-pin.component";
|
||||||
import { SshAgentPromptType } from "../../autofill/models/ssh-agent-setting";
|
import { SshAgentPromptType } from "../../autofill/models/ssh-agent-setting";
|
||||||
import { DesktopAutofillSettingsService } from "../../autofill/services/desktop-autofill-settings.service";
|
import { DesktopAutofillSettingsService } from "../../autofill/services/desktop-autofill-settings.service";
|
||||||
|
import { DesktopAutotypeService } from "../../autofill/services/desktop-autotype.service";
|
||||||
import { DesktopBiometricsService } from "../../key-management/biometrics/desktop.biometrics.service";
|
import { DesktopBiometricsService } from "../../key-management/biometrics/desktop.biometrics.service";
|
||||||
import { DesktopSettingsService } from "../../platform/services/desktop-settings.service";
|
import { DesktopSettingsService } from "../../platform/services/desktop-settings.service";
|
||||||
import { NativeMessagingManifestService } from "../services/native-messaging-manifest.service";
|
import { NativeMessagingManifestService } from "../services/native-messaging-manifest.service";
|
||||||
@@ -72,6 +74,7 @@ export class SettingsComponent implements OnInit, OnDestroy {
|
|||||||
showAlwaysShowDock = false;
|
showAlwaysShowDock = false;
|
||||||
requireEnableTray = false;
|
requireEnableTray = false;
|
||||||
showDuckDuckGoIntegrationOption = false;
|
showDuckDuckGoIntegrationOption = false;
|
||||||
|
showEnableAutotype = false;
|
||||||
showOpenAtLoginOption = false;
|
showOpenAtLoginOption = false;
|
||||||
isWindows: boolean;
|
isWindows: boolean;
|
||||||
isLinux: boolean;
|
isLinux: boolean;
|
||||||
@@ -133,6 +136,7 @@ export class SettingsComponent implements OnInit, OnDestroy {
|
|||||||
sshAgentPromptBehavior: SshAgentPromptType.Always,
|
sshAgentPromptBehavior: SshAgentPromptType.Always,
|
||||||
allowScreenshots: false,
|
allowScreenshots: false,
|
||||||
enableDuckDuckGoBrowserIntegration: false,
|
enableDuckDuckGoBrowserIntegration: false,
|
||||||
|
enableAutotype: false,
|
||||||
theme: [null as Theme | null],
|
theme: [null as Theme | null],
|
||||||
locale: [null as string | null],
|
locale: [null as string | null],
|
||||||
});
|
});
|
||||||
@@ -156,6 +160,7 @@ export class SettingsComponent implements OnInit, OnDestroy {
|
|||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
private userVerificationService: UserVerificationServiceAbstraction,
|
private userVerificationService: UserVerificationServiceAbstraction,
|
||||||
private desktopSettingsService: DesktopSettingsService,
|
private desktopSettingsService: DesktopSettingsService,
|
||||||
|
private desktopAutotypeService: DesktopAutotypeService,
|
||||||
private biometricStateService: BiometricStateService,
|
private biometricStateService: BiometricStateService,
|
||||||
private biometricsService: DesktopBiometricsService,
|
private biometricsService: DesktopBiometricsService,
|
||||||
private desktopAutofillSettingsService: DesktopAutofillSettingsService,
|
private desktopAutofillSettingsService: DesktopAutofillSettingsService,
|
||||||
@@ -236,9 +241,12 @@ export class SettingsComponent implements OnInit, OnDestroy {
|
|||||||
const activeAccount = await firstValueFrom(this.accountService.activeAccount$);
|
const activeAccount = await firstValueFrom(this.accountService.activeAccount$);
|
||||||
this.isLinux = (await this.platformUtilsService.getDevice()) === DeviceType.LinuxDesktop;
|
this.isLinux = (await this.platformUtilsService.getDevice()) === DeviceType.LinuxDesktop;
|
||||||
|
|
||||||
if (activeAccount == null || activeAccount.id == null) {
|
// Autotype is for Windows initially
|
||||||
return;
|
const isWindows = this.platformUtilsService.getDevice() === DeviceType.WindowsDesktop;
|
||||||
}
|
const windowsDesktopAutotypeFeatureFlag = await this.configService.getFeatureFlag(
|
||||||
|
FeatureFlag.WindowsDesktopAutotype,
|
||||||
|
);
|
||||||
|
this.showEnableAutotype = isWindows && windowsDesktopAutotypeFeatureFlag;
|
||||||
|
|
||||||
this.userHasMasterPassword = await this.userVerificationService.hasMasterPassword();
|
this.userHasMasterPassword = await this.userVerificationService.hasMasterPassword();
|
||||||
|
|
||||||
@@ -333,6 +341,7 @@ export class SettingsComponent implements OnInit, OnDestroy {
|
|||||||
this.desktopSettingsService.sshAgentPromptBehavior$,
|
this.desktopSettingsService.sshAgentPromptBehavior$,
|
||||||
),
|
),
|
||||||
allowScreenshots: !(await firstValueFrom(this.desktopSettingsService.preventScreenshots$)),
|
allowScreenshots: !(await firstValueFrom(this.desktopSettingsService.preventScreenshots$)),
|
||||||
|
enableAutotype: await firstValueFrom(this.desktopAutotypeService.autotypeEnabled$),
|
||||||
theme: await firstValueFrom(this.themeStateService.selectedTheme$),
|
theme: await firstValueFrom(this.themeStateService.selectedTheme$),
|
||||||
locale: await firstValueFrom(this.i18nService.userSetLocale$),
|
locale: await firstValueFrom(this.i18nService.userSetLocale$),
|
||||||
};
|
};
|
||||||
@@ -853,6 +862,10 @@ export class SettingsComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async saveEnableAutotype() {
|
||||||
|
await this.desktopAutotypeService.setAutotypeEnabledState(this.form.value.enableAutotype);
|
||||||
|
}
|
||||||
|
|
||||||
private async generateVaultTimeoutOptions(): Promise<VaultTimeoutOption[]> {
|
private async generateVaultTimeoutOptions(): Promise<VaultTimeoutOption[]> {
|
||||||
let vaultTimeoutOptions: VaultTimeoutOption[] = [
|
let vaultTimeoutOptions: VaultTimeoutOption[] = [
|
||||||
{ name: this.i18nService.t("oneMinute"), value: 1 },
|
{ name: this.i18nService.t("oneMinute"), value: 1 },
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { UserId } from "@bitwarden/common/types/guid";
|
|||||||
import { KeyService as KeyServiceAbstraction } from "@bitwarden/key-management";
|
import { KeyService as KeyServiceAbstraction } from "@bitwarden/key-management";
|
||||||
|
|
||||||
import { DesktopAutofillService } from "../../autofill/services/desktop-autofill.service";
|
import { DesktopAutofillService } from "../../autofill/services/desktop-autofill.service";
|
||||||
|
import { DesktopAutotypeService } from "../../autofill/services/desktop-autotype.service";
|
||||||
import { SshAgentService } from "../../autofill/services/ssh-agent.service";
|
import { SshAgentService } from "../../autofill/services/ssh-agent.service";
|
||||||
import { I18nRendererService } from "../../platform/services/i18n.renderer.service";
|
import { I18nRendererService } from "../../platform/services/i18n.renderer.service";
|
||||||
import { VersionService } from "../../platform/services/version.service";
|
import { VersionService } from "../../platform/services/version.service";
|
||||||
@@ -50,6 +51,7 @@ export class InitService {
|
|||||||
private versionService: VersionService,
|
private versionService: VersionService,
|
||||||
private sshAgentService: SshAgentService,
|
private sshAgentService: SshAgentService,
|
||||||
private autofillService: DesktopAutofillService,
|
private autofillService: DesktopAutofillService,
|
||||||
|
private autotypeService: DesktopAutotypeService,
|
||||||
private sdkLoadService: SdkLoadService,
|
private sdkLoadService: SdkLoadService,
|
||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
private bulkEncryptService: BulkEncryptService,
|
private bulkEncryptService: BulkEncryptService,
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ import {
|
|||||||
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
|
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
|
||||||
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||||
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
||||||
import { ClientType } from "@bitwarden/common/enums";
|
import { ClientType, DeviceType } from "@bitwarden/common/enums";
|
||||||
import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-management/abstractions/process-reload.service";
|
import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-management/abstractions/process-reload.service";
|
||||||
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
|
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
|
||||||
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
|
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
|
||||||
@@ -113,6 +113,7 @@ import { DesktopLoginComponentService } from "../../auth/login/desktop-login-com
|
|||||||
import { DesktopTwoFactorAuthDuoComponentService } from "../../auth/services/desktop-two-factor-auth-duo-component.service";
|
import { DesktopTwoFactorAuthDuoComponentService } from "../../auth/services/desktop-two-factor-auth-duo-component.service";
|
||||||
import { DesktopAutofillSettingsService } from "../../autofill/services/desktop-autofill-settings.service";
|
import { DesktopAutofillSettingsService } from "../../autofill/services/desktop-autofill-settings.service";
|
||||||
import { DesktopAutofillService } from "../../autofill/services/desktop-autofill.service";
|
import { DesktopAutofillService } from "../../autofill/services/desktop-autofill.service";
|
||||||
|
import { DesktopAutotypeService } from "../../autofill/services/desktop-autotype.service";
|
||||||
import { DesktopFido2UserInterfaceService } from "../../autofill/services/desktop-fido2-user-interface.service";
|
import { DesktopFido2UserInterfaceService } from "../../autofill/services/desktop-fido2-user-interface.service";
|
||||||
import { DesktopBiometricsService } from "../../key-management/biometrics/desktop.biometrics.service";
|
import { DesktopBiometricsService } from "../../key-management/biometrics/desktop.biometrics.service";
|
||||||
import { RendererBiometricsService } from "../../key-management/biometrics/renderer-biometrics.service";
|
import { RendererBiometricsService } from "../../key-management/biometrics/renderer-biometrics.service";
|
||||||
@@ -469,6 +470,20 @@ const safeProviders: SafeProvider[] = [
|
|||||||
useClass: DefaultSshImportPromptService,
|
useClass: DefaultSshImportPromptService,
|
||||||
deps: [DialogService, ToastService, PlatformUtilsServiceAbstraction, I18nServiceAbstraction],
|
deps: [DialogService, ToastService, PlatformUtilsServiceAbstraction, I18nServiceAbstraction],
|
||||||
}),
|
}),
|
||||||
|
safeProvider({
|
||||||
|
provide: DesktopAutotypeService,
|
||||||
|
useFactory: (
|
||||||
|
configService: ConfigService,
|
||||||
|
globalStateProvider: GlobalStateProvider,
|
||||||
|
platformUtilsService: PlatformUtilsServiceAbstraction,
|
||||||
|
) =>
|
||||||
|
new DesktopAutotypeService(
|
||||||
|
configService,
|
||||||
|
globalStateProvider,
|
||||||
|
platformUtilsService.getDevice() === DeviceType.WindowsDesktop,
|
||||||
|
),
|
||||||
|
deps: [ConfigService, GlobalStateProvider, PlatformUtilsServiceAbstraction],
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { DesktopAutotypeService } from "../services/desktop-autotype.service";
|
||||||
|
|
||||||
|
export class MainDesktopAutotypeService {
|
||||||
|
constructor(private desktopAutotypeService: DesktopAutotypeService) {}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.desktopAutotypeService.autotypeEnabled$.subscribe((enabled) => {
|
||||||
|
if (enabled) {
|
||||||
|
this.enableAutotype();
|
||||||
|
} else {
|
||||||
|
this.disableAutotype();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this will call into desktop native code
|
||||||
|
private enableAutotype() {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log("Enabling Autotype...");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this will call into desktop native code
|
||||||
|
private disableAutotype() {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log("Disabling Autotype...");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import { combineLatest, map, Observable, of } from "rxjs";
|
||||||
|
|
||||||
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
|
import {
|
||||||
|
GlobalStateProvider,
|
||||||
|
AUTOTYPE_SETTINGS_DISK,
|
||||||
|
KeyDefinition,
|
||||||
|
} from "@bitwarden/common/platform/state";
|
||||||
|
|
||||||
|
export const AUTOTYPE_ENABLED = new KeyDefinition<boolean>(
|
||||||
|
AUTOTYPE_SETTINGS_DISK,
|
||||||
|
"autotypeEnabled",
|
||||||
|
{ deserializer: (b) => b },
|
||||||
|
);
|
||||||
|
|
||||||
|
export class DesktopAutotypeService {
|
||||||
|
private readonly autotypeEnabledState = this.globalStateProvider.get(AUTOTYPE_ENABLED);
|
||||||
|
|
||||||
|
autotypeEnabled$: Observable<boolean> = of(false);
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private configService: ConfigService,
|
||||||
|
private globalStateProvider: GlobalStateProvider,
|
||||||
|
private isWindows: boolean,
|
||||||
|
) {
|
||||||
|
if (this.isWindows) {
|
||||||
|
this.autotypeEnabled$ = combineLatest([
|
||||||
|
this.autotypeEnabledState.state$,
|
||||||
|
this.configService.getFeatureFlag$(FeatureFlag.WindowsDesktopAutotype),
|
||||||
|
]).pipe(
|
||||||
|
map(
|
||||||
|
([autotypeEnabled, windowsDesktopAutotypeFeatureFlag]) =>
|
||||||
|
autotypeEnabled && windowsDesktopAutotypeFeatureFlag,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {}
|
||||||
|
|
||||||
|
async setAutotypeEnabledState(enabled: boolean): Promise<void> {
|
||||||
|
await this.autotypeEnabledState.update(() => enabled, {
|
||||||
|
shouldUpdate: (currentlyEnabled) => currentlyEnabled !== enabled,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3997,5 +3997,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"enableAutotype": {
|
||||||
|
"message": "Enable autotype shortcut"
|
||||||
|
},
|
||||||
|
"enableAutotypeDescription": {
|
||||||
|
"message": "Bitwarden does not validate input locations, be sure you are in the right window and field before using the shortcut."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,10 @@ import { MemoryStorageService as MemoryStorageServiceForStateProviders } from "@
|
|||||||
import { DefaultBiometricStateService } from "@bitwarden/key-management";
|
import { DefaultBiometricStateService } from "@bitwarden/key-management";
|
||||||
import { NodeCryptoFunctionService } from "@bitwarden/node/services/node-crypto-function.service";
|
import { NodeCryptoFunctionService } from "@bitwarden/node/services/node-crypto-function.service";
|
||||||
|
|
||||||
|
import { MainDesktopAutotypeService } from "./autofill/main/main-desktop-autotype.service";
|
||||||
import { MainSshAgentService } from "./autofill/main/main-ssh-agent.service";
|
import { MainSshAgentService } from "./autofill/main/main-ssh-agent.service";
|
||||||
import { DesktopAutofillSettingsService } from "./autofill/services/desktop-autofill-settings.service";
|
import { DesktopAutofillSettingsService } from "./autofill/services/desktop-autofill-settings.service";
|
||||||
|
import { DesktopAutotypeService } from "./autofill/services/desktop-autotype.service";
|
||||||
import { DesktopBiometricsService } from "./key-management/biometrics/desktop.biometrics.service";
|
import { DesktopBiometricsService } from "./key-management/biometrics/desktop.biometrics.service";
|
||||||
import { MainBiometricsIPCListener } from "./key-management/biometrics/main-biometrics-ipc.listener";
|
import { MainBiometricsIPCListener } from "./key-management/biometrics/main-biometrics-ipc.listener";
|
||||||
import { MainBiometricsService } from "./key-management/biometrics/main-biometrics.service";
|
import { MainBiometricsService } from "./key-management/biometrics/main-biometrics.service";
|
||||||
@@ -44,6 +46,7 @@ import { PowerMonitorMain } from "./main/power-monitor.main";
|
|||||||
import { TrayMain } from "./main/tray.main";
|
import { TrayMain } from "./main/tray.main";
|
||||||
import { UpdaterMain } from "./main/updater.main";
|
import { UpdaterMain } from "./main/updater.main";
|
||||||
import { WindowMain } from "./main/window.main";
|
import { WindowMain } from "./main/window.main";
|
||||||
|
import { SlimConfigService } from "./platform/config/slim-config.service";
|
||||||
import { NativeAutofillMain } from "./platform/main/autofill/native-autofill.main";
|
import { NativeAutofillMain } from "./platform/main/autofill/native-autofill.main";
|
||||||
import { ClipboardMain } from "./platform/main/clipboard.main";
|
import { ClipboardMain } from "./platform/main/clipboard.main";
|
||||||
import { DesktopCredentialStorageListener } from "./platform/main/desktop-credential-storage-listener";
|
import { DesktopCredentialStorageListener } from "./platform/main/desktop-credential-storage-listener";
|
||||||
@@ -85,6 +88,7 @@ export class Main {
|
|||||||
desktopAutofillSettingsService: DesktopAutofillSettingsService;
|
desktopAutofillSettingsService: DesktopAutofillSettingsService;
|
||||||
versionMain: VersionMain;
|
versionMain: VersionMain;
|
||||||
sshAgentService: MainSshAgentService;
|
sshAgentService: MainSshAgentService;
|
||||||
|
mainDesktopAutotypeService: MainDesktopAutotypeService;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
// Set paths for portable builds
|
// Set paths for portable builds
|
||||||
@@ -293,6 +297,15 @@ export class Main {
|
|||||||
|
|
||||||
this.nativeAutofillMain = new NativeAutofillMain(this.logService, this.windowMain);
|
this.nativeAutofillMain = new NativeAutofillMain(this.logService, this.windowMain);
|
||||||
void this.nativeAutofillMain.init();
|
void this.nativeAutofillMain.init();
|
||||||
|
|
||||||
|
this.mainDesktopAutotypeService = new MainDesktopAutotypeService(
|
||||||
|
new DesktopAutotypeService(
|
||||||
|
new SlimConfigService(this.environmentService, globalStateProvider),
|
||||||
|
globalStateProvider,
|
||||||
|
process.platform === "win32",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
this.mainDesktopAutotypeService.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
bootstrap() {
|
bootstrap() {
|
||||||
|
|||||||
66
apps/desktop/src/platform/config/slim-config.service.ts
Normal file
66
apps/desktop/src/platform/config/slim-config.service.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { combineLatest, map, Observable, throwError } from "rxjs";
|
||||||
|
import { SemVer } from "semver";
|
||||||
|
|
||||||
|
import {
|
||||||
|
FeatureFlag,
|
||||||
|
FeatureFlagValueType,
|
||||||
|
getFeatureFlagValue,
|
||||||
|
} from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
|
import { ServerConfig } from "@bitwarden/common/platform/abstractions/config/server-config";
|
||||||
|
import {
|
||||||
|
EnvironmentService,
|
||||||
|
Region,
|
||||||
|
} from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
|
import { ServerSettings } from "@bitwarden/common/platform/models/domain/server-settings";
|
||||||
|
import { GLOBAL_SERVER_CONFIGURATIONS } from "@bitwarden/common/platform/services/config/default-config.service";
|
||||||
|
import { GlobalStateProvider } from "@bitwarden/common/platform/state";
|
||||||
|
import { UserId } from "@bitwarden/user-core";
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOT FOR GENERAL USE
|
||||||
|
|
||||||
|
If you have more uses for the config service in the main process,
|
||||||
|
please reach out to platform.
|
||||||
|
*/
|
||||||
|
export class SlimConfigService implements ConfigService {
|
||||||
|
constructor(
|
||||||
|
private environmentService: EnvironmentService,
|
||||||
|
private globalStateProvider: GlobalStateProvider,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
serverConfig$: Observable<ServerConfig> = throwError(() => {
|
||||||
|
return new Error("Method not implemented.");
|
||||||
|
});
|
||||||
|
serverSettings$: Observable<ServerSettings> = throwError(() => {
|
||||||
|
return new Error("Method not implemented.");
|
||||||
|
});
|
||||||
|
cloudRegion$: Observable<Region> = throwError(() => {
|
||||||
|
return new Error("Method not implemented.");
|
||||||
|
});
|
||||||
|
getFeatureFlag$<Flag extends FeatureFlag>(key: Flag): Observable<FeatureFlagValueType<Flag>> {
|
||||||
|
return combineLatest([
|
||||||
|
this.environmentService.environment$,
|
||||||
|
this.globalStateProvider.get(GLOBAL_SERVER_CONFIGURATIONS).state$,
|
||||||
|
]).pipe(
|
||||||
|
map(([environment, serverConfig]) =>
|
||||||
|
getFeatureFlagValue(serverConfig[environment.getApiUrl()], key),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
userCachedFeatureFlag$<Flag extends FeatureFlag>(
|
||||||
|
key: Flag,
|
||||||
|
userId: UserId,
|
||||||
|
): Observable<FeatureFlagValueType<Flag>> {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
getFeatureFlag<Flag extends FeatureFlag>(key: Flag): Promise<FeatureFlagValueType<Flag>> {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
checkServerMeetsVersionRequirement$(minimumRequiredServerVersion: SemVer): Observable<boolean> {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
ensureConfigFetched(): Promise<void> {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@ export enum FeatureFlag {
|
|||||||
NotificationRefresh = "notification-refresh",
|
NotificationRefresh = "notification-refresh",
|
||||||
UseTreeWalkerApiForPageDetailsCollection = "use-tree-walker-api-for-page-details-collection",
|
UseTreeWalkerApiForPageDetailsCollection = "use-tree-walker-api-for-page-details-collection",
|
||||||
MacOsNativeCredentialSync = "macos-native-credential-sync",
|
MacOsNativeCredentialSync = "macos-native-credential-sync",
|
||||||
|
WindowsDesktopAutotype = "windows-desktop-autotype",
|
||||||
|
|
||||||
/* Billing */
|
/* Billing */
|
||||||
TrialPaymentOptional = "PM-8163-trial-payment",
|
TrialPaymentOptional = "PM-8163-trial-payment",
|
||||||
@@ -86,6 +87,7 @@ export const DefaultFeatureFlagValue = {
|
|||||||
[FeatureFlag.NotificationRefresh]: FALSE,
|
[FeatureFlag.NotificationRefresh]: FALSE,
|
||||||
[FeatureFlag.UseTreeWalkerApiForPageDetailsCollection]: FALSE,
|
[FeatureFlag.UseTreeWalkerApiForPageDetailsCollection]: FALSE,
|
||||||
[FeatureFlag.MacOsNativeCredentialSync]: FALSE,
|
[FeatureFlag.MacOsNativeCredentialSync]: FALSE,
|
||||||
|
[FeatureFlag.WindowsDesktopAutotype]: FALSE,
|
||||||
|
|
||||||
/* Data Insights and Reporting */
|
/* Data Insights and Reporting */
|
||||||
[FeatureFlag.EnableRiskInsightsNotifications]: FALSE,
|
[FeatureFlag.EnableRiskInsightsNotifications]: FALSE,
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ export const AUTOFILL_SETTINGS_DISK_LOCAL = new StateDefinition("autofillSetting
|
|||||||
web: "disk-local",
|
web: "disk-local",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const AUTOTYPE_SETTINGS_DISK = new StateDefinition("autotypeSettings", "disk");
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
|
|
||||||
export const NEW_WEB_LAYOUT_BANNER_DISK = new StateDefinition("newWebLayoutBanner", "disk", {
|
export const NEW_WEB_LAYOUT_BANNER_DISK = new StateDefinition("newWebLayoutBanner", "disk", {
|
||||||
|
|||||||
Reference in New Issue
Block a user