mirror of
https://github.com/bitwarden/browser
synced 2025-12-19 09:43:23 +00:00
* [PM-6426] Create TaskSchedulerService and update usage of long lived timeouts * [PM-6426] Implementing nextSync timeout using TaskScheduler * [PM-6426] Implementing systemClearClipboard using TaskScheduler * [PM-6426] Fixing race condition with setting/unsetting active alarms * [PM-6426] Implementing clear clipboard call on generatePasswordToClipboard with the TaskSchedulerService * [PM-6426] Implementing abortTimeout for Fido2ClientService using TaskSchedulerService * [PM-6426] Implementing reconnect timer timeout for NotificationService using the TaskSchedulerService * [PM-6426] Implementing reconnect timer timeout for NotificationService using the TaskSchedulerService * [PM-6426] Implementing sessionTimeout for LoginStrategyService using TaskSchedulerService * [PM-6426] Implementing eventUploadInterval using TaskScheduler * [PM-6426] Adding jest tests for the base TaskSchedulerService class * [PM-6426] Updating jest tests for GeneratePasswordToClipboardCommand * [PM-6426] Setting up the full sync process as an interval rather than a timeout * [PM-6426] Renaming the scheduleNextSync alarm name * [PM-6426] Fixing dependency references in services.module.ts * [PM-6426] Adding jest tests for added BrowserApi methods * [PM-6426] Refactoring small detail for how we identify the clear clipboard timeout in SystemService * [PM-6426] Ensuring that we await clearing an established scheduled task for the notification service * [PM-6426] Changing the name of the state definition for the TaskScheduler * [PM-6426] Implementing jest tests for the BrowserTaskSchedulerService * [PM-6426] Implementing jest tests for the BrowserTaskSchedulerService * [PM-6426] Adding jest tests for the base TaskSchedulerService class * [PM-6426] Finalizing jest tests for BrowserTaskScheduler class * [PM-6426] Finalizing documentation on BrowserTaskSchedulerService * [PM-6426] Fixing jest test for LoginStrategyService * [PM-6426] Implementing compatibility for the browser.alarms api * [PM-6426] Fixing how we check for the browser alarms api * [PM-6426] Adding jest tests to the BrowserApi implementation * [PM-6426] Aligning the implementation with our code guidelines for Angular components * [PM-6426] Fixing jest tests and lint errors * [PM-6426] Moving alarms api calls out of BrowserApi and structuring them within the BrowserTaskSchedulerService * [PM-6426] Reworking implementation to register handlers separately from the call to those handlers * [PM-6426] Adjusting how we register the fullSync scheduled task * [PM-6426] Implementing approach for incorporating the user UUID when setting task handlers * [PM-6426] Attempting to re-work implementation to facilitate userId-spcific alarms * [PM-6426] Refactoring smaller details of the implementation * [PM-6426] Working through the details of the implementation and setting up final refinments * [PM-6426] Fixing some issues surrounding duplicate alarms triggering * [PM-6426] Adjusting name for generate password to clipboard command task name * [PM-6426] Fixing generate password to clipboard command jest tests * [PM-6426] Working through jest tests and implementing a method to guard against setting a task without having a registered callback * [PM-6426] Working through jest tests and implementing a method to guard against setting a task without having a registered callback * [PM-6426] Implementing methodology for having a fallback to setTimeout if the browser context is lost in some manner * [PM-6426] Working through jest tests * [PM-6426] Working through jest tests * [PM-6426] Working through jest tests * [PM-6426] Working through jest tests * [PM-6426] Finalizing stepped setInterval implementation * [PM-6426] Implementing Jest tests for DefaultTaskSchedulerService * [PM-6426] Adjusting jest tests * [PM-6426] Adjusting jest tests * [PM-6426] Adjusting jest tests * [PM-6426] Fixing issues identified in code review * [PM-6426] Fixing issues identified in code review * [PM-6426] Removing user-based alarms and fixing an issue found with setting steppedd alarm interavals * [PM-6426] Removing user-based alarms and fixing an issue found with setting steppedd alarm interavals * [PM-6426] Fixing issue with typing information on a test * [PM-6426] Using the getUpperBoundDelayInMinutes method to handle setting stepped alarms and setTimeout fallbacks * [PM-6426] Removing the potential for the TaskScheduler to be optional * [PM-6426] Reworking implementation to leverage subscription based deregistration of alarms * [PM-6426] Fixing jest tests * [PM-6426] Implementing foreground and background task scheduler services to avoid duplication of task scheudlers and to have the background setup as a fallback to the poopup tasks * [PM-6426] Implementing foreground and background task scheduler services to avoid duplication of task scheudlers and to have the background setup as a fallback to the poopup tasks * [PM-6426] Merging main into branch * [PM-6426] Fixing issues with the CLI Service Container implementation * [PM-6426] Reworking swallowed promises to contain a catch statement allow us to debug potential issues with registrations of alarms * [PM-6426] Adding jest tests to the ForegroundTaskSchedulerService and the BackgroundTaskSchedulerService * [PM-6426] Adding jest tests to the ForegroundTaskSchedulerService and the BackgroundTaskSchedulerService * [PM-6426] Adding jest tests to the ForegroundTaskSchedulerService and the BackgroundTaskSchedulerService * [PM-6426] Adding jest tests to the ForegroundTaskSchedulerService and the BackgroundTaskSchedulerService * [PM-6426] Adjusting implementation based on code review feedback * [PM-6426] Reworking file structure * [PM-6426] Reworking file structure * [PM-6426] Adding comments to provide clarity on how the login strategy cache experiation state is used * [PM-6426] Catching and logging erorrs that appear from methods that return a promise within VaultTimeoutService
160 lines
6.0 KiB
TypeScript
160 lines
6.0 KiB
TypeScript
import { firstValueFrom, map, Subscription, timeout } from "rxjs";
|
|
|
|
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 { 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 { SystemService as SystemServiceAbstraction } from "../abstractions/system.service";
|
|
import { BiometricStateService } from "../biometrics/biometric-state.service";
|
|
import { Utils } from "../misc/utils";
|
|
import { ScheduledTaskNames } from "../scheduling/scheduled-task-name.enum";
|
|
import { TaskSchedulerService } from "../scheduling/task-scheduler.service";
|
|
|
|
export class SystemService implements SystemServiceAbstraction {
|
|
private reloadInterval: any = null;
|
|
private clearClipboardTimeoutSubscription: Subscription;
|
|
private clearClipboardTimeoutFunction: () => Promise<any> = null;
|
|
|
|
constructor(
|
|
private pinService: PinServiceAbstraction,
|
|
private messagingService: MessagingService,
|
|
private platformUtilsService: PlatformUtilsService,
|
|
private reloadCallback: () => Promise<void> = null,
|
|
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
|
private vaultTimeoutSettingsService: VaultTimeoutSettingsService,
|
|
private biometricStateService: BiometricStateService,
|
|
private accountService: AccountService,
|
|
private taskSchedulerService: TaskSchedulerService,
|
|
) {
|
|
this.taskSchedulerService.registerTaskHandler(
|
|
ScheduledTaskNames.systemClearClipboardTimeout,
|
|
() => this.clearPendingClipboard(),
|
|
);
|
|
}
|
|
|
|
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> {
|
|
this.clearClipboardTimeoutSubscription?.unsubscribe();
|
|
|
|
if (Utils.isNullOrWhitespace(clipboardValue)) {
|
|
return;
|
|
}
|
|
|
|
let taskTimeoutInMs = timeoutMs;
|
|
if (!taskTimeoutInMs) {
|
|
const clearClipboardDelayInSeconds = await firstValueFrom(
|
|
this.autofillSettingsService.clearClipboardDelay$,
|
|
);
|
|
taskTimeoutInMs = clearClipboardDelayInSeconds ? clearClipboardDelayInSeconds * 1000 : null;
|
|
}
|
|
|
|
if (!taskTimeoutInMs) {
|
|
return;
|
|
}
|
|
|
|
this.clearClipboardTimeoutFunction = async () => {
|
|
const clipboardValueNow = await this.platformUtilsService.readFromClipboard();
|
|
if (clipboardValue === clipboardValueNow) {
|
|
this.platformUtilsService.copyToClipboard("", { clearing: true });
|
|
}
|
|
};
|
|
|
|
this.clearClipboardTimeoutSubscription = this.taskSchedulerService.setTimeout(
|
|
ScheduledTaskNames.systemClearClipboardTimeout,
|
|
taskTimeoutInMs,
|
|
);
|
|
}
|
|
|
|
async clearPendingClipboard() {
|
|
if (this.clearClipboardTimeoutFunction != null) {
|
|
await this.clearClipboardTimeoutFunction();
|
|
this.clearClipboardTimeoutFunction = null;
|
|
}
|
|
}
|
|
}
|