1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-18 09:13:33 +00:00

[PM-6426] Create TaskSchedulerService and update long lived timeouts in the extension to leverage the new service (#8566)

* [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
This commit is contained in:
Cesar Gonzalez
2024-07-15 10:32:30 -05:00
committed by GitHub
parent 5fcf4bbd10
commit 974162b1a4
39 changed files with 1854 additions and 283 deletions

View File

@@ -7,6 +7,8 @@ import { AuthenticationStatus } from "../../auth/enums/authentication-status";
import { EventData } from "../../models/data/event.data";
import { EventRequest } from "../../models/request/event.request";
import { LogService } from "../../platform/abstractions/log.service";
import { ScheduledTaskNames } from "../../platform/scheduling/scheduled-task-name.enum";
import { TaskSchedulerService } from "../../platform/scheduling/task-scheduler.service";
import { StateProvider } from "../../platform/state";
import { UserId } from "../../types/guid";
@@ -19,7 +21,12 @@ export class EventUploadService implements EventUploadServiceAbstraction {
private stateProvider: StateProvider,
private logService: LogService,
private authService: AuthService,
) {}
private taskSchedulerService: TaskSchedulerService,
) {
this.taskSchedulerService.registerTaskHandler(ScheduledTaskNames.eventUploadsInterval, () =>
this.uploadEvents(),
);
}
init(checkOnInterval: boolean) {
if (this.inited) {
@@ -28,10 +35,11 @@ export class EventUploadService implements EventUploadServiceAbstraction {
this.inited = true;
if (checkOnInterval) {
// 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
this.uploadEvents();
setInterval(() => this.uploadEvents(), 60 * 1000); // check every 60 seconds
void this.uploadEvents();
this.taskSchedulerService.setInterval(
ScheduledTaskNames.eventUploadsInterval,
60 * 1000, // check every 60 seconds
);
}
}

View File

@@ -1,6 +1,6 @@
import * as signalR from "@microsoft/signalr";
import * as signalRMsgPack from "@microsoft/signalr-protocol-msgpack";
import { firstValueFrom } from "rxjs";
import { firstValueFrom, Subscription } from "rxjs";
import { LogoutReason } from "@bitwarden/auth/common";
@@ -20,6 +20,8 @@ import { EnvironmentService } from "../platform/abstractions/environment.service
import { LogService } from "../platform/abstractions/log.service";
import { MessagingService } from "../platform/abstractions/messaging.service";
import { StateService } from "../platform/abstractions/state.service";
import { ScheduledTaskNames } from "../platform/scheduling/scheduled-task-name.enum";
import { TaskSchedulerService } from "../platform/scheduling/task-scheduler.service";
import { SyncService } from "../vault/abstractions/sync/sync.service.abstraction";
export class NotificationsService implements NotificationsServiceAbstraction {
@@ -28,7 +30,8 @@ export class NotificationsService implements NotificationsServiceAbstraction {
private connected = false;
private inited = false;
private inactive = false;
private reconnectTimer: any = null;
private reconnectTimerSubscription: Subscription;
private isSyncingOnReconnect = true;
constructor(
private logService: LogService,
@@ -40,7 +43,12 @@ export class NotificationsService implements NotificationsServiceAbstraction {
private stateService: StateService,
private authService: AuthService,
private messagingService: MessagingService,
private taskSchedulerService: TaskSchedulerService,
) {
this.taskSchedulerService.registerTaskHandler(
ScheduledTaskNames.notificationsReconnectTimeout,
() => this.reconnect(this.isSyncingOnReconnect),
);
this.environmentService.environment$.subscribe(() => {
if (!this.inited) {
return;
@@ -213,10 +221,8 @@ export class NotificationsService implements NotificationsServiceAbstraction {
}
private async reconnect(sync: boolean) {
if (this.reconnectTimer != null) {
clearTimeout(this.reconnectTimer);
this.reconnectTimer = null;
}
this.reconnectTimerSubscription?.unsubscribe();
if (this.connected || !this.inited || this.inactive) {
return;
}
@@ -236,7 +242,11 @@ export class NotificationsService implements NotificationsServiceAbstraction {
}
if (!this.connected) {
this.reconnectTimer = setTimeout(() => this.reconnect(sync), this.random(120000, 300000));
this.isSyncingOnReconnect = sync;
this.reconnectTimerSubscription = this.taskSchedulerService.setTimeout(
ScheduledTaskNames.notificationsReconnectTimeout,
this.random(120000, 300000),
);
}
}

View File

@@ -2,6 +2,8 @@ import { MockProxy, any, mock } from "jest-mock-extended";
import { BehaviorSubject, from, of } from "rxjs";
import { LogoutReason } from "@bitwarden/auth/common";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { TaskSchedulerService } from "@bitwarden/common/platform/scheduling";
import { FakeAccountService, mockAccountServiceWith } from "../../../spec/fake-account-service";
import { SearchService } from "../../abstractions/search.service";
@@ -37,6 +39,8 @@ describe("VaultTimeoutService", () => {
let authService: MockProxy<AuthService>;
let vaultTimeoutSettingsService: MockProxy<VaultTimeoutSettingsService>;
let stateEventRunnerService: MockProxy<StateEventRunnerService>;
let taskSchedulerService: MockProxy<TaskSchedulerService>;
let logService: MockProxy<LogService>;
let lockedCallback: jest.Mock<Promise<void>, [userId: string]>;
let loggedOutCallback: jest.Mock<Promise<void>, [logoutReason: LogoutReason, userId?: string]>;
@@ -60,6 +64,8 @@ describe("VaultTimeoutService", () => {
authService = mock();
vaultTimeoutSettingsService = mock();
stateEventRunnerService = mock();
taskSchedulerService = mock<TaskSchedulerService>();
logService = mock<LogService>();
lockedCallback = jest.fn();
loggedOutCallback = jest.fn();
@@ -85,6 +91,8 @@ describe("VaultTimeoutService", () => {
authService,
vaultTimeoutSettingsService,
stateEventRunnerService,
taskSchedulerService,
logService,
lockedCallback,
loggedOutCallback,
);

View File

@@ -1,6 +1,8 @@
import { combineLatest, filter, firstValueFrom, map, switchMap, timeout } from "rxjs";
import { LogoutReason } from "@bitwarden/auth/common";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { TaskSchedulerService, ScheduledTaskNames } from "@bitwarden/common/platform/scheduling";
import { SearchService } from "../../abstractions/search.service";
import { VaultTimeoutSettingsService } from "../../abstractions/vault-timeout/vault-timeout-settings.service";
@@ -35,12 +37,19 @@ export class VaultTimeoutService implements VaultTimeoutServiceAbstraction {
private authService: AuthService,
private vaultTimeoutSettingsService: VaultTimeoutSettingsService,
private stateEventRunnerService: StateEventRunnerService,
private taskSchedulerService: TaskSchedulerService,
protected logService: LogService,
private lockedCallback: (userId?: string) => Promise<void> = null,
private loggedOutCallback: (
logoutReason: LogoutReason,
userId?: string,
) => Promise<void> = null,
) {}
) {
this.taskSchedulerService.registerTaskHandler(
ScheduledTaskNames.vaultTimeoutCheckInterval,
() => this.checkVaultTimeout(),
);
}
async init(checkOnInterval: boolean) {
if (this.inited) {
@@ -54,10 +63,11 @@ export class VaultTimeoutService implements VaultTimeoutServiceAbstraction {
}
startCheck() {
// 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
this.checkVaultTimeout();
setInterval(() => this.checkVaultTimeout(), 10 * 1000); // check every 10 seconds
this.checkVaultTimeout().catch((error) => this.logService.error(error));
this.taskSchedulerService.setInterval(
ScheduledTaskNames.vaultTimeoutCheckInterval,
10 * 1000, // check every 10 seconds
);
}
async checkVaultTimeout(): Promise<void> {