mirror of
https://github.com/bitwarden/browser.git
synced 2025-02-06 23:51:28 +01:00
Move process reload ownership to key-management (#10853)
This commit is contained in:
parent
eff9a423da
commit
74dabb97bf
@ -75,6 +75,8 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs
|
|||||||
import { DefaultBillingAccountProfileStateService } from "@bitwarden/common/billing/services/account/billing-account-profile-state.service";
|
import { DefaultBillingAccountProfileStateService } from "@bitwarden/common/billing/services/account/billing-account-profile-state.service";
|
||||||
import { ClientType } from "@bitwarden/common/enums";
|
import { ClientType } from "@bitwarden/common/enums";
|
||||||
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 { ProcessReloadService } from "@bitwarden/common/key-management/services/process-reload.service";
|
||||||
import { AppIdService as AppIdServiceAbstraction } from "@bitwarden/common/platform/abstractions/app-id.service";
|
import { AppIdService as AppIdServiceAbstraction } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction";
|
import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
@ -270,6 +272,7 @@ import CommandsBackground from "./commands.background";
|
|||||||
import IdleBackground from "./idle.background";
|
import IdleBackground from "./idle.background";
|
||||||
import { NativeMessagingBackground } from "./nativeMessaging.background";
|
import { NativeMessagingBackground } from "./nativeMessaging.background";
|
||||||
import RuntimeBackground from "./runtime.background";
|
import RuntimeBackground from "./runtime.background";
|
||||||
|
|
||||||
export default class MainBackground {
|
export default class MainBackground {
|
||||||
messagingService: MessageSender;
|
messagingService: MessageSender;
|
||||||
storageService: BrowserLocalStorageService;
|
storageService: BrowserLocalStorageService;
|
||||||
@ -314,6 +317,7 @@ export default class MainBackground {
|
|||||||
badgeSettingsService: BadgeSettingsServiceAbstraction;
|
badgeSettingsService: BadgeSettingsServiceAbstraction;
|
||||||
domainSettingsService: DomainSettingsService;
|
domainSettingsService: DomainSettingsService;
|
||||||
systemService: SystemServiceAbstraction;
|
systemService: SystemServiceAbstraction;
|
||||||
|
processReloadService: ProcessReloadServiceAbstraction;
|
||||||
eventCollectionService: EventCollectionServiceAbstraction;
|
eventCollectionService: EventCollectionServiceAbstraction;
|
||||||
eventUploadService: EventUploadServiceAbstraction;
|
eventUploadService: EventUploadServiceAbstraction;
|
||||||
policyService: InternalPolicyServiceAbstraction;
|
policyService: InternalPolicyServiceAbstraction;
|
||||||
@ -408,7 +412,7 @@ export default class MainBackground {
|
|||||||
await this.refreshMenu(true);
|
await this.refreshMenu(true);
|
||||||
if (this.systemService != null) {
|
if (this.systemService != null) {
|
||||||
await this.systemService.clearPendingClipboard();
|
await this.systemService.clearPendingClipboard();
|
||||||
await this.systemService.startProcessReload(this.authService);
|
await this.processReloadService.startProcessReload(this.authService);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1088,15 +1092,18 @@ export default class MainBackground {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.systemService = new SystemService(
|
this.systemService = new SystemService(
|
||||||
|
this.platformUtilsService,
|
||||||
|
this.autofillSettingsService,
|
||||||
|
this.taskSchedulerService,
|
||||||
|
);
|
||||||
|
|
||||||
|
this.processReloadService = new ProcessReloadService(
|
||||||
this.pinService,
|
this.pinService,
|
||||||
this.messagingService,
|
this.messagingService,
|
||||||
this.platformUtilsService,
|
|
||||||
systemUtilsServiceReloadCallback,
|
systemUtilsServiceReloadCallback,
|
||||||
this.autofillSettingsService,
|
|
||||||
this.vaultTimeoutSettingsService,
|
this.vaultTimeoutSettingsService,
|
||||||
this.biometricStateService,
|
this.biometricStateService,
|
||||||
this.accountService,
|
this.accountService,
|
||||||
this.taskSchedulerService,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Other fields
|
// Other fields
|
||||||
@ -1122,7 +1129,7 @@ export default class MainBackground {
|
|||||||
this.platformUtilsService as BrowserPlatformUtilsService,
|
this.platformUtilsService as BrowserPlatformUtilsService,
|
||||||
this.notificationsService,
|
this.notificationsService,
|
||||||
this.autofillSettingsService,
|
this.autofillSettingsService,
|
||||||
this.systemService,
|
this.processReloadService,
|
||||||
this.environmentService,
|
this.environmentService,
|
||||||
this.messagingService,
|
this.messagingService,
|
||||||
this.logService,
|
this.logService,
|
||||||
@ -1551,7 +1558,7 @@ export default class MainBackground {
|
|||||||
await this.mainContextMenuHandler?.noAccess();
|
await this.mainContextMenuHandler?.noAccess();
|
||||||
await this.notificationsService.updateConnection(false);
|
await this.notificationsService.updateConnection(false);
|
||||||
await this.systemService.clearPendingClipboard();
|
await this.systemService.clearPendingClipboard();
|
||||||
await this.systemService.startProcessReload(this.authService);
|
await this.processReloadService.startProcessReload(this.authService);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async needsStorageReseed(userId: UserId): Promise<boolean> {
|
private async needsStorageReseed(userId: UserId): Promise<boolean> {
|
||||||
|
@ -6,10 +6,10 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
|
|||||||
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 { 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 { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
import { SystemService } from "@bitwarden/common/platform/abstractions/system.service";
|
|
||||||
import { devFlagEnabled } from "@bitwarden/common/platform/misc/flags";
|
import { devFlagEnabled } from "@bitwarden/common/platform/misc/flags";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
@ -40,7 +40,7 @@ export default class RuntimeBackground {
|
|||||||
private platformUtilsService: BrowserPlatformUtilsService,
|
private platformUtilsService: BrowserPlatformUtilsService,
|
||||||
private notificationsService: NotificationsService,
|
private notificationsService: NotificationsService,
|
||||||
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
||||||
private systemService: SystemService,
|
private processReloadSerivce: ProcessReloadServiceAbstraction,
|
||||||
private environmentService: BrowserEnvironmentService,
|
private environmentService: BrowserEnvironmentService,
|
||||||
private messagingService: MessagingService,
|
private messagingService: MessagingService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
@ -216,7 +216,7 @@ export default class RuntimeBackground {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await this.notificationsService.updateConnection(msg.command === "loggedIn");
|
await this.notificationsService.updateConnection(msg.command === "loggedIn");
|
||||||
this.systemService.cancelProcessReload();
|
this.processReloadSerivce.cancelProcessReload();
|
||||||
|
|
||||||
if (item) {
|
if (item) {
|
||||||
await BrowserApi.focusWindow(item.commandToRetry.sender.tab.windowId);
|
await BrowserApi.focusWindow(item.commandToRetry.sender.tab.windowId);
|
||||||
|
@ -32,6 +32,7 @@ import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authenticatio
|
|||||||
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
||||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
|
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
|
||||||
|
import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-management/abstractions/process-reload.service";
|
||||||
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
@ -142,6 +143,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
private notificationsService: NotificationsService,
|
private notificationsService: NotificationsService,
|
||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
private systemService: SystemService,
|
private systemService: SystemService,
|
||||||
|
private processReloadService: ProcessReloadServiceAbstraction,
|
||||||
private stateService: StateService,
|
private stateService: StateService,
|
||||||
private eventUploadService: EventUploadService,
|
private eventUploadService: EventUploadService,
|
||||||
private policyService: InternalPolicyService,
|
private policyService: InternalPolicyService,
|
||||||
@ -213,7 +215,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
this.updateAppMenu();
|
this.updateAppMenu();
|
||||||
this.systemService.cancelProcessReload();
|
this.processReloadService.cancelProcessReload();
|
||||||
break;
|
break;
|
||||||
case "loggedOut":
|
case "loggedOut":
|
||||||
this.modalService.closeAll();
|
this.modalService.closeAll();
|
||||||
@ -224,7 +226,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
this.updateAppMenu();
|
this.updateAppMenu();
|
||||||
await this.systemService.clearPendingClipboard();
|
await this.systemService.clearPendingClipboard();
|
||||||
await this.systemService.startProcessReload(this.authService);
|
await this.processReloadService.startProcessReload(this.authService);
|
||||||
break;
|
break;
|
||||||
case "authBlocked":
|
case "authBlocked":
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
@ -268,15 +270,15 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
this.notificationsService.updateConnection();
|
this.notificationsService.updateConnection();
|
||||||
await this.updateAppMenu();
|
await this.updateAppMenu();
|
||||||
await this.systemService.clearPendingClipboard();
|
await this.systemService.clearPendingClipboard();
|
||||||
await this.systemService.startProcessReload(this.authService);
|
await this.processReloadService.startProcessReload(this.authService);
|
||||||
break;
|
break;
|
||||||
case "startProcessReload":
|
case "startProcessReload":
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
this.systemService.startProcessReload(this.authService);
|
this.processReloadService.startProcessReload(this.authService);
|
||||||
break;
|
break;
|
||||||
case "cancelProcessReload":
|
case "cancelProcessReload":
|
||||||
this.systemService.cancelProcessReload();
|
this.processReloadService.cancelProcessReload();
|
||||||
break;
|
break;
|
||||||
case "reloadProcess":
|
case "reloadProcess":
|
||||||
ipc.platform.reloadProcess();
|
ipc.platform.reloadProcess();
|
||||||
|
@ -37,6 +37,8 @@ import {
|
|||||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.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 } from "@bitwarden/common/enums";
|
||||||
|
import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-management/abstractions/process-reload.service";
|
||||||
|
import { ProcessReloadService } from "@bitwarden/common/key-management/services/process-reload.service";
|
||||||
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||||
import {
|
import {
|
||||||
CryptoService,
|
CryptoService,
|
||||||
@ -196,16 +198,22 @@ const safeProviders: SafeProvider[] = [
|
|||||||
safeProvider({
|
safeProvider({
|
||||||
provide: SystemServiceAbstraction,
|
provide: SystemServiceAbstraction,
|
||||||
useClass: SystemService,
|
useClass: SystemService,
|
||||||
|
deps: [
|
||||||
|
PlatformUtilsServiceAbstraction,
|
||||||
|
AutofillSettingsServiceAbstraction,
|
||||||
|
TaskSchedulerService,
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
safeProvider({
|
||||||
|
provide: ProcessReloadServiceAbstraction,
|
||||||
|
useClass: ProcessReloadService,
|
||||||
deps: [
|
deps: [
|
||||||
PinServiceAbstraction,
|
PinServiceAbstraction,
|
||||||
MessagingServiceAbstraction,
|
MessagingServiceAbstraction,
|
||||||
PlatformUtilsServiceAbstraction,
|
|
||||||
RELOAD_CALLBACK,
|
RELOAD_CALLBACK,
|
||||||
AutofillSettingsServiceAbstraction,
|
|
||||||
VaultTimeoutSettingsService,
|
VaultTimeoutSettingsService,
|
||||||
BiometricStateService,
|
BiometricStateService,
|
||||||
AccountServiceAbstraction,
|
AccountServiceAbstraction,
|
||||||
TaskSchedulerService,
|
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
safeProvider({
|
safeProvider({
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
import { AuthService } from "../../auth/abstractions/auth.service";
|
||||||
|
|
||||||
|
export abstract class ProcessReloadServiceAbstraction {
|
||||||
|
abstract startProcessReload(authService: AuthService): Promise<void>;
|
||||||
|
abstract cancelProcessReload(): void;
|
||||||
|
}
|
@ -0,0 +1,106 @@
|
|||||||
|
import { firstValueFrom, map, timeout } from "rxjs";
|
||||||
|
|
||||||
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
|
import { BiometricStateService } from "@bitwarden/key-management";
|
||||||
|
|
||||||
|
import { PinServiceAbstraction } from "../../../../auth/src/common/abstractions";
|
||||||
|
import { VaultTimeoutSettingsService } from "../../abstractions/vault-timeout/vault-timeout-settings.service";
|
||||||
|
import { AccountService } from "../../auth/abstractions/account.service";
|
||||||
|
import { AuthService } from "../../auth/abstractions/auth.service";
|
||||||
|
import { AuthenticationStatus } from "../../auth/enums/authentication-status";
|
||||||
|
import { VaultTimeoutAction } from "../../enums/vault-timeout-action.enum";
|
||||||
|
import { UserId } from "../../types/guid";
|
||||||
|
import { ProcessReloadServiceAbstraction } from "../abstractions/process-reload.service";
|
||||||
|
|
||||||
|
export class ProcessReloadService implements ProcessReloadServiceAbstraction {
|
||||||
|
private reloadInterval: any = null;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private pinService: PinServiceAbstraction,
|
||||||
|
private messagingService: MessagingService,
|
||||||
|
private reloadCallback: () => Promise<void> = null,
|
||||||
|
private vaultTimeoutSettingsService: VaultTimeoutSettingsService,
|
||||||
|
private biometricStateService: BiometricStateService,
|
||||||
|
private accountService: AccountService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async startProcessReload(authService: AuthService): Promise<void> {
|
||||||
|
const accounts = await firstValueFrom(this.accountService.accounts$);
|
||||||
|
if (accounts != null) {
|
||||||
|
const keys = Object.keys(accounts);
|
||||||
|
if (keys.length > 0) {
|
||||||
|
for (const userId of keys) {
|
||||||
|
let status = await firstValueFrom(authService.authStatusFor$(userId as UserId));
|
||||||
|
status = await authService.getAuthStatus(userId);
|
||||||
|
if (status === AuthenticationStatus.Unlocked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A reloadInterval has already been set and is executing
|
||||||
|
if (this.reloadInterval != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is an active user, check if they have a pinKeyEncryptedUserKeyEphemeral. If so, prevent process reload upon lock.
|
||||||
|
const userId = (await firstValueFrom(this.accountService.activeAccount$))?.id;
|
||||||
|
if (userId != null) {
|
||||||
|
const ephemeralPin = await this.pinService.getPinKeyEncryptedUserKeyEphemeral(userId);
|
||||||
|
if (ephemeralPin != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cancelProcessReload();
|
||||||
|
await this.executeProcessReload();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async executeProcessReload() {
|
||||||
|
const biometricLockedFingerprintValidated = await firstValueFrom(
|
||||||
|
this.biometricStateService.fingerprintValidated$,
|
||||||
|
);
|
||||||
|
if (!biometricLockedFingerprintValidated) {
|
||||||
|
clearInterval(this.reloadInterval);
|
||||||
|
this.reloadInterval = null;
|
||||||
|
|
||||||
|
const activeUserId = await firstValueFrom(
|
||||||
|
this.accountService.activeAccount$.pipe(
|
||||||
|
map((a) => a?.id),
|
||||||
|
timeout(500),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
// Replace current active user if they will be logged out on reload
|
||||||
|
if (activeUserId != null) {
|
||||||
|
const timeoutAction = await firstValueFrom(
|
||||||
|
this.vaultTimeoutSettingsService
|
||||||
|
.getVaultTimeoutActionByUserId$(activeUserId)
|
||||||
|
.pipe(timeout(500)), // safety feature to avoid this call hanging and stopping process reload from clearing memory
|
||||||
|
);
|
||||||
|
if (timeoutAction === VaultTimeoutAction.LogOut) {
|
||||||
|
const nextUser = await firstValueFrom(
|
||||||
|
this.accountService.nextUpAccount$.pipe(map((account) => account?.id ?? null)),
|
||||||
|
);
|
||||||
|
await this.accountService.switchAccount(nextUser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.messagingService.send("reloadProcess");
|
||||||
|
if (this.reloadCallback != null) {
|
||||||
|
await this.reloadCallback();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.reloadInterval == null) {
|
||||||
|
this.reloadInterval = setInterval(async () => await this.executeProcessReload(), 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelProcessReload(): void {
|
||||||
|
if (this.reloadInterval != null) {
|
||||||
|
clearInterval(this.reloadInterval);
|
||||||
|
this.reloadInterval = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,4 @@
|
|||||||
import { AuthService } from "../../auth/abstractions/auth.service";
|
|
||||||
|
|
||||||
export abstract class SystemService {
|
export abstract class SystemService {
|
||||||
abstract startProcessReload(authService: AuthService): Promise<void>;
|
|
||||||
abstract cancelProcessReload(): void;
|
|
||||||
abstract clearClipboard(clipboardValue: string, timeoutMs?: number): Promise<void>;
|
abstract clearClipboard(clipboardValue: string, timeoutMs?: number): Promise<void>;
|
||||||
abstract clearPendingClipboard(): Promise<any>;
|
abstract clearPendingClipboard(): Promise<any>;
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,6 @@
|
|||||||
import { firstValueFrom, map, Subscription, timeout } from "rxjs";
|
import { firstValueFrom, Subscription } from "rxjs";
|
||||||
|
|
||||||
import { BiometricStateService } from "@bitwarden/key-management";
|
|
||||||
|
|
||||||
import { PinServiceAbstraction } from "../../../../auth/src/common/abstractions";
|
|
||||||
import { VaultTimeoutSettingsService } from "../../abstractions/vault-timeout/vault-timeout-settings.service";
|
|
||||||
import { AccountService } from "../../auth/abstractions/account.service";
|
|
||||||
import { AuthService } from "../../auth/abstractions/auth.service";
|
|
||||||
import { AuthenticationStatus } from "../../auth/enums/authentication-status";
|
|
||||||
import { AutofillSettingsServiceAbstraction } from "../../autofill/services/autofill-settings.service";
|
import { AutofillSettingsServiceAbstraction } from "../../autofill/services/autofill-settings.service";
|
||||||
import { VaultTimeoutAction } from "../../enums/vault-timeout-action.enum";
|
|
||||||
import { UserId } from "../../types/guid";
|
|
||||||
import { MessagingService } from "../abstractions/messaging.service";
|
|
||||||
import { PlatformUtilsService } from "../abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "../abstractions/platform-utils.service";
|
||||||
import { SystemService as SystemServiceAbstraction } from "../abstractions/system.service";
|
import { SystemService as SystemServiceAbstraction } from "../abstractions/system.service";
|
||||||
import { Utils } from "../misc/utils";
|
import { Utils } from "../misc/utils";
|
||||||
@ -18,19 +8,12 @@ import { ScheduledTaskNames } from "../scheduling/scheduled-task-name.enum";
|
|||||||
import { TaskSchedulerService } from "../scheduling/task-scheduler.service";
|
import { TaskSchedulerService } from "../scheduling/task-scheduler.service";
|
||||||
|
|
||||||
export class SystemService implements SystemServiceAbstraction {
|
export class SystemService implements SystemServiceAbstraction {
|
||||||
private reloadInterval: any = null;
|
|
||||||
private clearClipboardTimeoutSubscription: Subscription;
|
private clearClipboardTimeoutSubscription: Subscription;
|
||||||
private clearClipboardTimeoutFunction: () => Promise<any> = null;
|
private clearClipboardTimeoutFunction: () => Promise<any> = null;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private pinService: PinServiceAbstraction,
|
|
||||||
private messagingService: MessagingService,
|
|
||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
private reloadCallback: () => Promise<void> = null,
|
|
||||||
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
||||||
private vaultTimeoutSettingsService: VaultTimeoutSettingsService,
|
|
||||||
private biometricStateService: BiometricStateService,
|
|
||||||
private accountService: AccountService,
|
|
||||||
private taskSchedulerService: TaskSchedulerService,
|
private taskSchedulerService: TaskSchedulerService,
|
||||||
) {
|
) {
|
||||||
this.taskSchedulerService.registerTaskHandler(
|
this.taskSchedulerService.registerTaskHandler(
|
||||||
@ -39,86 +22,6 @@ export class SystemService implements SystemServiceAbstraction {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async startProcessReload(authService: AuthService): Promise<void> {
|
|
||||||
const accounts = await firstValueFrom(this.accountService.accounts$);
|
|
||||||
if (accounts != null) {
|
|
||||||
const keys = Object.keys(accounts);
|
|
||||||
if (keys.length > 0) {
|
|
||||||
for (const userId of keys) {
|
|
||||||
let status = await firstValueFrom(authService.authStatusFor$(userId as UserId));
|
|
||||||
status = await authService.getAuthStatus(userId);
|
|
||||||
if (status === AuthenticationStatus.Unlocked) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A reloadInterval has already been set and is executing
|
|
||||||
if (this.reloadInterval != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is an active user, check if they have a pinKeyEncryptedUserKeyEphemeral. If so, prevent process reload upon lock.
|
|
||||||
const userId = (await firstValueFrom(this.accountService.activeAccount$))?.id;
|
|
||||||
if (userId != null) {
|
|
||||||
const ephemeralPin = await this.pinService.getPinKeyEncryptedUserKeyEphemeral(userId);
|
|
||||||
if (ephemeralPin != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.cancelProcessReload();
|
|
||||||
await this.executeProcessReload();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async executeProcessReload() {
|
|
||||||
const biometricLockedFingerprintValidated = await firstValueFrom(
|
|
||||||
this.biometricStateService.fingerprintValidated$,
|
|
||||||
);
|
|
||||||
if (!biometricLockedFingerprintValidated) {
|
|
||||||
clearInterval(this.reloadInterval);
|
|
||||||
this.reloadInterval = null;
|
|
||||||
|
|
||||||
const activeUserId = await firstValueFrom(
|
|
||||||
this.accountService.activeAccount$.pipe(
|
|
||||||
map((a) => a?.id),
|
|
||||||
timeout(500),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
// Replace current active user if they will be logged out on reload
|
|
||||||
if (activeUserId != null) {
|
|
||||||
const timeoutAction = await firstValueFrom(
|
|
||||||
this.vaultTimeoutSettingsService
|
|
||||||
.getVaultTimeoutActionByUserId$(activeUserId)
|
|
||||||
.pipe(timeout(500)), // safety feature to avoid this call hanging and stopping process reload from clearing memory
|
|
||||||
);
|
|
||||||
if (timeoutAction === VaultTimeoutAction.LogOut) {
|
|
||||||
const nextUser = await firstValueFrom(
|
|
||||||
this.accountService.nextUpAccount$.pipe(map((account) => account?.id ?? null)),
|
|
||||||
);
|
|
||||||
await this.accountService.switchAccount(nextUser);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.messagingService.send("reloadProcess");
|
|
||||||
if (this.reloadCallback != null) {
|
|
||||||
await this.reloadCallback();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.reloadInterval == null) {
|
|
||||||
this.reloadInterval = setInterval(async () => await this.executeProcessReload(), 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelProcessReload(): void {
|
|
||||||
if (this.reloadInterval != null) {
|
|
||||||
clearInterval(this.reloadInterval);
|
|
||||||
this.reloadInterval = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async clearClipboard(clipboardValue: string, timeoutMs: number = null): Promise<void> {
|
async clearClipboard(clipboardValue: string, timeoutMs: number = null): Promise<void> {
|
||||||
this.clearClipboardTimeoutSubscription?.unsubscribe();
|
this.clearClipboardTimeoutSubscription?.unsubscribe();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user