mirror of
https://github.com/bitwarden/browser.git
synced 2024-10-04 05:08:06 +02:00
[PM-6426] Working through jest tests
This commit is contained in:
parent
b34b2efa0c
commit
2891c2c8a6
@ -764,6 +764,7 @@ export default class MainBackground {
|
||||
this.stateEventRunnerService,
|
||||
lockedCallback,
|
||||
logoutCallback,
|
||||
this.taskSchedulerService,
|
||||
);
|
||||
this.containerService = new ContainerService(this.cryptoService, this.encryptService);
|
||||
|
||||
|
@ -39,7 +39,7 @@ function setupGlobalBrowserMock(overrides: Partial<chrome.alarms.Alarm> = {}) {
|
||||
}
|
||||
const userUuid = "user-uuid" as UserId;
|
||||
function getAlarmNameMock(taskName: string) {
|
||||
return `${userUuid}__${taskName}`;
|
||||
return `${taskName}__${userUuid}`;
|
||||
}
|
||||
|
||||
describe("BrowserTaskSchedulerService", () => {
|
||||
@ -252,9 +252,13 @@ describe("BrowserTaskSchedulerService", () => {
|
||||
);
|
||||
|
||||
expect(globalThis.setInterval).toHaveBeenCalledWith(expect.any(Function), intervalInMs);
|
||||
expect(chrome.alarms.create).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it.todo(
|
||||
"sets up stepped alarms that trigger behavior after the first minute of setInterval execution",
|
||||
() => {},
|
||||
);
|
||||
|
||||
it("creates an interval alarm", async () => {
|
||||
const periodInMinutes = 2;
|
||||
const initialDelayInMs = 1000;
|
||||
@ -267,7 +271,7 @@ describe("BrowserTaskSchedulerService", () => {
|
||||
|
||||
expect(chrome.alarms.create).toHaveBeenCalledWith(
|
||||
getAlarmNameMock(ScheduledTaskNames.loginStrategySessionTimeout),
|
||||
{ periodInMinutes, delayInMinutes: initialDelayInMs / 1000 / 60 },
|
||||
{ periodInMinutes, delayInMinutes: 0.5 },
|
||||
expect.any(Function),
|
||||
);
|
||||
});
|
||||
|
@ -64,8 +64,8 @@ export class BrowserTaskSchedulerServiceImplementation
|
||||
// The alarm previously scheduled will be used as a backup in case the setTimeout fails.
|
||||
if (delayInMinutes < 1) {
|
||||
return globalThis.setTimeout(async () => {
|
||||
await this.triggerTask(alarmName);
|
||||
await this.clearScheduledAlarm(alarmName);
|
||||
await this.triggerTask(alarmName);
|
||||
}, delayInMs);
|
||||
}
|
||||
}
|
||||
@ -84,21 +84,56 @@ export class BrowserTaskSchedulerServiceImplementation
|
||||
intervalInMs: number,
|
||||
initialDelayInMs?: number,
|
||||
): Promise<number | NodeJS.Timeout> {
|
||||
const intervalInMinutes = intervalInMs / 1000 / 60;
|
||||
if (intervalInMinutes < 1) {
|
||||
return super.setInterval(taskName, intervalInMs);
|
||||
}
|
||||
|
||||
this.validateRegisteredTask(taskName);
|
||||
|
||||
const intervalInMinutes = intervalInMs / 1000 / 60;
|
||||
const alarmName = await this.getActiveUserAlarmName(taskName);
|
||||
const initialDelayInMinutes = initialDelayInMs ? initialDelayInMs / 1000 / 60 : undefined;
|
||||
const initialDelayInMinutes = initialDelayInMs
|
||||
? initialDelayInMs / 1000 / 60
|
||||
: intervalInMinutes;
|
||||
|
||||
if (intervalInMinutes < 1) {
|
||||
return this.setupSteppedIntervalAlarms(taskName, alarmName, intervalInMinutes, intervalInMs);
|
||||
}
|
||||
|
||||
await this.scheduleAlarm(alarmName, {
|
||||
periodInMinutes: intervalInMinutes,
|
||||
delayInMinutes: initialDelayInMinutes ?? intervalInMinutes,
|
||||
periodInMinutes: this.getUpperBoundDelayInMinutes(intervalInMinutes),
|
||||
delayInMinutes: this.getUpperBoundDelayInMinutes(initialDelayInMinutes),
|
||||
});
|
||||
}
|
||||
|
||||
private async setupSteppedIntervalAlarms(
|
||||
taskName: ScheduledTaskName,
|
||||
alarmName: string,
|
||||
intervalInMinutes: number,
|
||||
intervalInMs: number,
|
||||
) {
|
||||
let elapsedMs = 0;
|
||||
const intervalId: number | NodeJS.Timeout = globalThis.setInterval(async () => {
|
||||
elapsedMs += intervalInMs;
|
||||
const elapsedMinutes = elapsedMs / 1000 / 60;
|
||||
if (elapsedMinutes >= this.getAlarmMinDelayInMinutes()) {
|
||||
globalThis.clearInterval(intervalId);
|
||||
return;
|
||||
}
|
||||
await this.triggerTask(alarmName, intervalInMinutes);
|
||||
}, intervalInMs);
|
||||
|
||||
const numberOfAlarmsToCreate = Math.ceil(1 / intervalInMinutes);
|
||||
for (let i = 0; i < numberOfAlarmsToCreate; i++) {
|
||||
const steppedAlarmName = `${alarmName}__${i}`;
|
||||
const periodInMinutes = this.getAlarmMinDelayInMinutes() + i * intervalInMinutes;
|
||||
await this.clearScheduledAlarm(steppedAlarmName);
|
||||
await this.clearScheduledAlarm(`${taskName}__${i}`);
|
||||
|
||||
await this.scheduleAlarm(steppedAlarmName, {
|
||||
periodInMinutes: this.getUpperBoundDelayInMinutes(periodInMinutes),
|
||||
});
|
||||
}
|
||||
|
||||
return intervalId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears a scheduled task by its task identifier. If the task identifier
|
||||
* contains a task name, it will clear the browser extension alarm with that
|
||||
@ -308,7 +343,7 @@ export class BrowserTaskSchedulerServiceImplementation
|
||||
return taskName;
|
||||
}
|
||||
|
||||
return `${activeUserId}__${taskName}`;
|
||||
return `${taskName}__${activeUserId}`;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -318,7 +353,7 @@ export class BrowserTaskSchedulerServiceImplementation
|
||||
* @param alarmName - The alarm name to parse.
|
||||
*/
|
||||
private getTaskFromAlarmName(alarmName: string): ScheduledTaskName {
|
||||
const activeUserTask = alarmName.split("__")[1] as ScheduledTaskName;
|
||||
const activeUserTask = alarmName.split("__")[0] as ScheduledTaskName;
|
||||
if (activeUserTask) {
|
||||
return activeUserTask;
|
||||
}
|
||||
@ -392,6 +427,10 @@ export class BrowserTaskSchedulerServiceImplementation
|
||||
return typeof browser !== "undefined" && !!browser.alarms;
|
||||
}
|
||||
|
||||
private getAlarmMinDelayInMinutes(): number {
|
||||
return this.isNonChromeEnvironment() ? 1 : 0.5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the upper bound delay in minutes for a given delay in minutes. This is
|
||||
* used to ensure that the delay is at least 1 minute in non-Chrome environments.
|
||||
@ -400,7 +439,6 @@ export class BrowserTaskSchedulerServiceImplementation
|
||||
* @param delayInMinutes - The delay in minutes.
|
||||
*/
|
||||
private getUpperBoundDelayInMinutes(delayInMinutes: number): number {
|
||||
const minDelayInMinutes = this.isNonChromeEnvironment() ? 1 : 0.5;
|
||||
return Math.max(minDelayInMinutes, delayInMinutes);
|
||||
return Math.max(this.getAlarmMinDelayInMinutes(), delayInMinutes);
|
||||
}
|
||||
}
|
||||
|
@ -4,16 +4,13 @@ import { SafariApp } from "../../browser/safariApp";
|
||||
|
||||
export default class VaultTimeoutService extends BaseVaultTimeoutService {
|
||||
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();
|
||||
if (this.platformUtilsService.isSafari()) {
|
||||
// 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.checkSafari();
|
||||
} else {
|
||||
setInterval(() => this.checkVaultTimeout(), 10 * 1000); // check every 10 seconds
|
||||
void this.checkVaultTimeout();
|
||||
void this.checkSafari();
|
||||
return;
|
||||
}
|
||||
|
||||
super.startCheck();
|
||||
}
|
||||
|
||||
// This is a work-around to safari adding an arbitrary delay to setTimeout and
|
||||
|
@ -668,6 +668,7 @@ const safeProviders: SafeProvider[] = [
|
||||
StateEventRunnerService,
|
||||
LOCKED_CALLBACK,
|
||||
LOGOUT_CALLBACK,
|
||||
TaskSchedulerService,
|
||||
],
|
||||
}),
|
||||
safeProvider({
|
||||
|
@ -6,6 +6,7 @@ export const ScheduledTaskNames = {
|
||||
fido2ClientAbortTimeout: "fido2ClientAbortTimeout",
|
||||
scheduleNextSyncInterval: "scheduleNextSyncInterval",
|
||||
eventUploadsInterval: "eventUploadsInterval",
|
||||
vaultTimeoutCheckInterval: "vaultTimeoutCheckInterval",
|
||||
} as const;
|
||||
|
||||
export type ScheduledTaskName = (typeof ScheduledTaskNames)[keyof typeof ScheduledTaskNames];
|
||||
|
@ -1,5 +1,8 @@
|
||||
import { combineLatest, firstValueFrom, switchMap } from "rxjs";
|
||||
|
||||
import { TaskSchedulerService } from "@bitwarden/common/platform/abstractions/task-scheduler.service";
|
||||
import { ScheduledTaskNames } from "@bitwarden/common/platform/enums/scheduled-task-name.enum";
|
||||
|
||||
import { SearchService } from "../../abstractions/search.service";
|
||||
import { VaultTimeoutSettingsService } from "../../abstractions/vault-timeout/vault-timeout-settings.service";
|
||||
import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "../../abstractions/vault-timeout/vault-timeout.service";
|
||||
@ -35,7 +38,13 @@ export class VaultTimeoutService implements VaultTimeoutServiceAbstraction {
|
||||
private stateEventRunnerService: StateEventRunnerService,
|
||||
private lockedCallback: (userId?: string) => Promise<void> = null,
|
||||
private loggedOutCallback: (expired: boolean, userId?: string) => Promise<void> = null,
|
||||
) {}
|
||||
private taskSchedulerService?: TaskSchedulerService,
|
||||
) {
|
||||
void this.taskSchedulerService?.registerTaskHandler(
|
||||
ScheduledTaskNames.vaultTimeoutCheckInterval,
|
||||
() => this.checkVaultTimeout(),
|
||||
);
|
||||
}
|
||||
|
||||
async init(checkOnInterval: boolean) {
|
||||
if (this.inited) {
|
||||
@ -49,10 +58,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
|
||||
void this.checkVaultTimeout();
|
||||
void this.taskSchedulerService?.setInterval(
|
||||
ScheduledTaskNames.vaultTimeoutCheckInterval,
|
||||
10 * 1000, // check every 10 seconds
|
||||
);
|
||||
}
|
||||
|
||||
async checkVaultTimeout(): Promise<void> {
|
||||
|
Loading…
Reference in New Issue
Block a user