mirror of
https://github.com/bitwarden/browser.git
synced 2024-09-13 01:58:44 +02:00
[PM-6426] Implementing approach for incorporating the user UUID when setting task handlers
This commit is contained in:
parent
8fdc9df4a7
commit
6cb2577f90
@ -17,8 +17,9 @@ export class GeneratePasswordToClipboardCommand {
|
||||
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
||||
private taskSchedulerService: BrowserTaskSchedulerService,
|
||||
) {
|
||||
this.taskSchedulerService.registerTaskHandler(ScheduledTaskNames.clearClipboardTimeout, () =>
|
||||
ClearClipboard.run(),
|
||||
void this.taskSchedulerService.registerTaskHandler(
|
||||
ScheduledTaskNames.clearClipboardTimeout,
|
||||
() => ClearClipboard.run(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -448,8 +448,9 @@ export default class MainBackground {
|
||||
this.logService,
|
||||
this.stateProvider,
|
||||
);
|
||||
this.taskSchedulerService.registerTaskHandler(ScheduledTaskNames.scheduleNextSyncInterval, () =>
|
||||
this.fullSync(),
|
||||
void this.taskSchedulerService.registerTaskHandler(
|
||||
ScheduledTaskNames.scheduleNextSyncInterval,
|
||||
() => this.fullSync(),
|
||||
);
|
||||
this.environmentService = new BrowserEnvironmentService(
|
||||
this.logService,
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
import { Observable } from "rxjs";
|
||||
import { BehaviorSubject, Observable } from "rxjs";
|
||||
|
||||
import { TaskIdentifier } from "@bitwarden/common/platform/abstractions/task-scheduler.service";
|
||||
import { ScheduledTaskNames } from "@bitwarden/common/platform/enums/scheduled-task-name.enum";
|
||||
import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service";
|
||||
import { GlobalState, StateProvider } from "@bitwarden/common/platform/state";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import { ActiveAlarm } from "./abstractions/browser-task-scheduler.service";
|
||||
import { BrowserTaskSchedulerService } from "./browser-task-scheduler.service";
|
||||
@ -18,6 +19,7 @@ jest.mock("rxjs", () => ({
|
||||
|
||||
// TODO CG - Likely need to rethink how to test this service a bit more carefully.
|
||||
describe("BrowserTaskSchedulerService", () => {
|
||||
let activeUserIdMock$: BehaviorSubject<UserId>;
|
||||
let logService: MockProxy<ConsoleLogService>;
|
||||
let stateProvider: MockProxy<StateProvider>;
|
||||
let browserTaskSchedulerService: BrowserTaskSchedulerService;
|
||||
@ -41,8 +43,10 @@ describe("BrowserTaskSchedulerService", () => {
|
||||
createInfo: { delayInMinutes: 1, periodInMinutes: undefined },
|
||||
}),
|
||||
];
|
||||
activeUserIdMock$ = new BehaviorSubject("user-uuid" as UserId);
|
||||
logService = mock<ConsoleLogService>();
|
||||
stateProvider = mock<StateProvider>({
|
||||
activeUserId$: activeUserIdMock$,
|
||||
getGlobal: jest.fn(() =>
|
||||
mock<GlobalState<any>>({
|
||||
state$: mock<Observable<any>>(),
|
||||
@ -108,7 +112,7 @@ describe("BrowserTaskSchedulerService", () => {
|
||||
const callback = jest.fn();
|
||||
const delayInMs = 999;
|
||||
jest.spyOn(globalThis, "setTimeout");
|
||||
browserTaskSchedulerService.registerTaskHandler(
|
||||
await browserTaskSchedulerService.registerTaskHandler(
|
||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||
callback,
|
||||
);
|
||||
@ -132,7 +136,7 @@ describe("BrowserTaskSchedulerService", () => {
|
||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||
);
|
||||
const callback = jest.fn();
|
||||
browserTaskSchedulerService.registerTaskHandler(
|
||||
await browserTaskSchedulerService.registerTaskHandler(
|
||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||
callback,
|
||||
);
|
||||
@ -153,7 +157,7 @@ describe("BrowserTaskSchedulerService", () => {
|
||||
it("creates a timeout alarm", async () => {
|
||||
const callback = jest.fn();
|
||||
const delayInMinutes = 2;
|
||||
browserTaskSchedulerService.registerTaskHandler(
|
||||
await browserTaskSchedulerService.registerTaskHandler(
|
||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||
callback,
|
||||
);
|
||||
@ -179,7 +183,7 @@ describe("BrowserTaskSchedulerService", () => {
|
||||
}),
|
||||
);
|
||||
jest.spyOn(browserTaskSchedulerService, "createAlarm");
|
||||
browserTaskSchedulerService.registerTaskHandler(
|
||||
await browserTaskSchedulerService.registerTaskHandler(
|
||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||
callback,
|
||||
);
|
||||
@ -210,7 +214,7 @@ describe("BrowserTaskSchedulerService", () => {
|
||||
const callback = jest.fn();
|
||||
const intervalInMs = 999;
|
||||
jest.spyOn(globalThis, "setInterval");
|
||||
browserTaskSchedulerService.registerTaskHandler(
|
||||
await browserTaskSchedulerService.registerTaskHandler(
|
||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||
callback,
|
||||
);
|
||||
@ -235,7 +239,7 @@ describe("BrowserTaskSchedulerService", () => {
|
||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||
);
|
||||
const callback = jest.fn();
|
||||
browserTaskSchedulerService.registerTaskHandler(
|
||||
await browserTaskSchedulerService.registerTaskHandler(
|
||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||
callback,
|
||||
);
|
||||
@ -257,7 +261,7 @@ describe("BrowserTaskSchedulerService", () => {
|
||||
const callback = jest.fn();
|
||||
const periodInMinutes = 2;
|
||||
const initialDelayInMs = 1000;
|
||||
browserTaskSchedulerService.registerTaskHandler(
|
||||
await browserTaskSchedulerService.registerTaskHandler(
|
||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||
callback,
|
||||
);
|
||||
|
@ -30,11 +30,8 @@ export class BrowserTaskSchedulerService
|
||||
readonly activeAlarms$: Observable<ActiveAlarm[]>;
|
||||
private recoveredAlarms: Set<string> = new Set();
|
||||
|
||||
constructor(
|
||||
logService: LogService,
|
||||
private stateProvider: StateProvider,
|
||||
) {
|
||||
super(logService);
|
||||
constructor(logService: LogService, stateProvider: StateProvider) {
|
||||
super(logService, stateProvider);
|
||||
|
||||
this.activeAlarmsState = this.stateProvider.getGlobal(ACTIVE_ALARMS);
|
||||
this.activeAlarms$ = this.activeAlarmsState.state$.pipe(
|
||||
|
@ -255,7 +255,7 @@ const safeProviders: SafeProvider[] = [
|
||||
safeProvider({
|
||||
provide: TaskSchedulerService,
|
||||
useClass: DefaultTaskSchedulerService,
|
||||
deps: [LogServiceAbstraction],
|
||||
deps: [LogServiceAbstraction, StateProvider],
|
||||
}),
|
||||
];
|
||||
|
||||
|
@ -1130,7 +1130,7 @@ const safeProviders: SafeProvider[] = [
|
||||
safeProvider({
|
||||
provide: TaskSchedulerService,
|
||||
useClass: DefaultTaskSchedulerService,
|
||||
deps: [LogService],
|
||||
deps: [LogService, StateProvider],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: ProviderApiServiceAbstraction,
|
||||
|
@ -115,7 +115,7 @@ export class LoginStrategyService implements LoginStrategyServiceAbstraction {
|
||||
this.authRequestPushNotificationState = this.stateProvider.get(
|
||||
AUTH_REQUEST_PUSH_NOTIFICATION_KEY,
|
||||
);
|
||||
this.taskSchedulerService.registerTaskHandler(
|
||||
void this.taskSchedulerService.registerTaskHandler(
|
||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||
() => this.clearCache(),
|
||||
);
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { ScheduledTaskName } from "../enums/scheduled-task-name.enum";
|
||||
import { StateProvider } from "../state";
|
||||
|
||||
import { LogService } from "./log.service";
|
||||
|
||||
@ -11,11 +12,14 @@ export type TaskIdentifier = {
|
||||
export abstract class TaskSchedulerService {
|
||||
protected taskHandlers: Map<string, () => void>;
|
||||
|
||||
constructor(protected logService: LogService) {}
|
||||
constructor(
|
||||
protected logService: LogService,
|
||||
protected stateProvider: StateProvider,
|
||||
) {}
|
||||
|
||||
abstract registerTaskHandler(taskName: ScheduledTaskName, handler: () => void): void;
|
||||
abstract registerTaskHandler(taskName: ScheduledTaskName, handler: () => void): Promise<void>;
|
||||
|
||||
abstract unregisterTaskHandler(taskName: ScheduledTaskName): void;
|
||||
abstract unregisterTaskHandler(taskName: ScheduledTaskName): Promise<void>;
|
||||
|
||||
abstract setTimeout(
|
||||
taskName: ScheduledTaskName,
|
||||
|
@ -1,14 +1,34 @@
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
|
||||
import { UserId } from "../../../../common/src/types/guid";
|
||||
import { LogService } from "../abstractions/log.service";
|
||||
import { ScheduledTaskNames } from "../enums/scheduled-task-name.enum";
|
||||
import { StateProvider } from "../state";
|
||||
|
||||
import { DefaultTaskSchedulerService } from "./default-task-scheduler.service";
|
||||
|
||||
describe("TaskSchedulerService", () => {
|
||||
const callback = jest.fn();
|
||||
const delayInMs = 1000;
|
||||
const intervalInMs = 1100;
|
||||
let activeUserIdMock$: BehaviorSubject<UserId>;
|
||||
let logService: MockProxy<LogService>;
|
||||
let stateProvider: MockProxy<StateProvider>;
|
||||
let taskSchedulerService: DefaultTaskSchedulerService;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
taskSchedulerService = new DefaultTaskSchedulerService();
|
||||
activeUserIdMock$ = new BehaviorSubject<UserId>("user-uuid" as UserId);
|
||||
logService = mock<LogService>();
|
||||
stateProvider = mock<StateProvider>({
|
||||
activeUserId$: activeUserIdMock$,
|
||||
});
|
||||
taskSchedulerService = new DefaultTaskSchedulerService(logService, stateProvider);
|
||||
void taskSchedulerService.registerTaskHandler(
|
||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||
callback,
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -17,7 +37,10 @@ describe("TaskSchedulerService", () => {
|
||||
});
|
||||
|
||||
it("sets a timeout and returns the timeout id", async () => {
|
||||
const timeoutId = await taskSchedulerService.setTimeout(callback, delayInMs);
|
||||
const timeoutId = await taskSchedulerService.setTimeout(
|
||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||
delayInMs,
|
||||
);
|
||||
|
||||
expect(timeoutId).toBeDefined();
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
@ -28,7 +51,10 @@ describe("TaskSchedulerService", () => {
|
||||
});
|
||||
|
||||
it("sets an interval timeout and results the interval id", async () => {
|
||||
const intervalId = await taskSchedulerService.setInterval(callback, intervalInMs);
|
||||
const intervalId = await taskSchedulerService.setInterval(
|
||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||
intervalInMs,
|
||||
);
|
||||
|
||||
expect(intervalId).toBeDefined();
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
@ -43,7 +69,10 @@ describe("TaskSchedulerService", () => {
|
||||
});
|
||||
|
||||
it("clears scheduled tasks using the timeout id", async () => {
|
||||
const timeoutId = await taskSchedulerService.setTimeout(callback, delayInMs);
|
||||
const timeoutId = await taskSchedulerService.setTimeout(
|
||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||
delayInMs,
|
||||
);
|
||||
|
||||
expect(timeoutId).toBeDefined();
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
@ -56,7 +85,10 @@ describe("TaskSchedulerService", () => {
|
||||
});
|
||||
|
||||
it("clears scheduled tasks using the interval id", async () => {
|
||||
const intervalId = await taskSchedulerService.setInterval(callback, intervalInMs);
|
||||
const intervalId = await taskSchedulerService.setInterval(
|
||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||
intervalInMs,
|
||||
);
|
||||
|
||||
expect(intervalId).toBeDefined();
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
|
@ -1,26 +1,31 @@
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { LogService } from "../abstractions/log.service";
|
||||
import { TaskIdentifier, TaskSchedulerService } from "../abstractions/task-scheduler.service";
|
||||
import { ScheduledTaskName } from "../enums/scheduled-task-name.enum";
|
||||
import { StateProvider } from "../state";
|
||||
|
||||
export class DefaultTaskSchedulerService extends TaskSchedulerService {
|
||||
constructor(logService: LogService) {
|
||||
super(logService);
|
||||
constructor(logService: LogService, stateProvider: StateProvider) {
|
||||
super(logService, stateProvider);
|
||||
|
||||
this.taskHandlers = new Map();
|
||||
}
|
||||
|
||||
registerTaskHandler(taskName: ScheduledTaskName, handler: () => void): void {
|
||||
const existingHandler = this.taskHandlers.get(taskName);
|
||||
async registerTaskHandler(taskName: ScheduledTaskName, handler: () => void): Promise<void> {
|
||||
const activeUserTaskName = await this.getActiveUserTaskName(taskName);
|
||||
const existingHandler = this.taskHandlers.get(activeUserTaskName);
|
||||
if (existingHandler) {
|
||||
this.logService.warning(`Task handler for ${taskName} already exists. Overwriting.`);
|
||||
this.unregisterTaskHandler(taskName);
|
||||
await this.unregisterTaskHandler(taskName);
|
||||
}
|
||||
|
||||
this.taskHandlers.set(taskName, handler);
|
||||
this.taskHandlers.set(activeUserTaskName, handler);
|
||||
}
|
||||
|
||||
unregisterTaskHandler(taskName: ScheduledTaskName): void {
|
||||
this.taskHandlers.delete(taskName);
|
||||
async unregisterTaskHandler(taskName: ScheduledTaskName): Promise<void> {
|
||||
const activeUserTaskName = await this.getActiveUserTaskName(taskName);
|
||||
this.taskHandlers.delete(activeUserTaskName);
|
||||
}
|
||||
|
||||
protected triggerTask(taskName: ScheduledTaskName, _periodInMinutes?: number): void {
|
||||
@ -72,4 +77,13 @@ export class DefaultTaskSchedulerService extends TaskSchedulerService {
|
||||
globalThis.clearInterval(taskIdentifier.intervalId);
|
||||
}
|
||||
}
|
||||
|
||||
private async getActiveUserTaskName(taskName: ScheduledTaskName): Promise<string> {
|
||||
const activeUserId = await firstValueFrom(this.stateProvider.activeUserId$);
|
||||
if (!activeUserId) {
|
||||
return taskName;
|
||||
}
|
||||
|
||||
return `${activeUserId}_${taskName}`;
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ export class SystemService implements SystemServiceAbstraction {
|
||||
private biometricStateService: BiometricStateService,
|
||||
private taskSchedulerService: TaskSchedulerService,
|
||||
) {
|
||||
this.taskSchedulerService.registerTaskHandler(
|
||||
void this.taskSchedulerService.registerTaskHandler(
|
||||
ScheduledTaskNames.systemClearClipboardTimeout,
|
||||
() => this.clearPendingClipboard(),
|
||||
);
|
||||
|
@ -23,8 +23,9 @@ export class EventUploadService implements EventUploadServiceAbstraction {
|
||||
private authService: AuthService,
|
||||
private taskSchedulerService: TaskSchedulerService,
|
||||
) {
|
||||
this.taskSchedulerService.registerTaskHandler(ScheduledTaskNames.eventUploadsInterval, () =>
|
||||
this.uploadEvents(),
|
||||
void this.taskSchedulerService.registerTaskHandler(
|
||||
ScheduledTaskNames.eventUploadsInterval,
|
||||
() => this.uploadEvents(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ export class NotificationsService implements NotificationsServiceAbstraction {
|
||||
private messagingService: MessagingService,
|
||||
private taskSchedulerService: TaskSchedulerService,
|
||||
) {
|
||||
this.taskSchedulerService.registerTaskHandler(
|
||||
void this.taskSchedulerService.registerTaskHandler(
|
||||
ScheduledTaskNames.notificationsReconnectTimeout,
|
||||
() => this.reconnect(this.isSyncingOnReconnect),
|
||||
);
|
||||
|
@ -63,8 +63,9 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
||||
private taskSchedulerService: TaskSchedulerService,
|
||||
private logService?: LogService,
|
||||
) {
|
||||
this.taskSchedulerService.registerTaskHandler(ScheduledTaskNames.fido2ClientAbortTimeout, () =>
|
||||
this.timeoutAbortController?.abort(),
|
||||
void this.taskSchedulerService.registerTaskHandler(
|
||||
ScheduledTaskNames.fido2ClientAbortTimeout,
|
||||
() => this.timeoutAbortController?.abort(),
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user