mirror of
https://github.com/bitwarden/browser
synced 2026-01-27 23:03:45 +00:00
feat: use new service as the init trigger
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { Inject, Injectable, DOCUMENT } from "@angular/core";
|
||||
import { Inject, Injectable, DOCUMENT, Type } from "@angular/core";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { Initializable } from "@bitwarden/angular/platform/abstractions/decentralized-init.service";
|
||||
import { AbstractThemingService } from "@bitwarden/angular/platform/services/theming/theming.service.abstraction";
|
||||
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
|
||||
import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/common/abstractions/event/event-upload.service";
|
||||
@@ -31,7 +32,7 @@ import { BiometricMessageHandlerService } from "../../services/biometric-message
|
||||
import { NativeMessagingService } from "../../services/native-messaging.service";
|
||||
|
||||
@Injectable()
|
||||
export class InitService {
|
||||
export class InitService implements Initializable {
|
||||
constructor(
|
||||
@Inject(WINDOW) private win: Window,
|
||||
private syncService: SyncServiceAbstraction,
|
||||
@@ -59,46 +60,46 @@ export class InitService {
|
||||
private readonly migrationRunner: MigrationRunner,
|
||||
) {}
|
||||
|
||||
init() {
|
||||
return async () => {
|
||||
await this.sdkLoadService.loadAndInit();
|
||||
await this.sshAgentService.init();
|
||||
this.nativeMessagingService.init();
|
||||
await this.migrationRunner.waitForCompletion(); // Desktop will run migrations in the main process
|
||||
this.encryptService.init(this.configService);
|
||||
dependencies: Type<Initializable>[] = [];
|
||||
|
||||
const accounts = await firstValueFrom(this.accountService.accounts$);
|
||||
const setUserKeyInMemoryPromises = [];
|
||||
for (const userId of Object.keys(accounts) as UserId[]) {
|
||||
// For each acct, we must await the process of setting the user key in memory
|
||||
// if the auto user key is set to avoid race conditions of any code trying to access
|
||||
// the user key from mem.
|
||||
setUserKeyInMemoryPromises.push(
|
||||
this.userAutoUnlockKeyService.setUserKeyInMemoryIfAutoUserKeySet(userId),
|
||||
);
|
||||
}
|
||||
await Promise.all(setUserKeyInMemoryPromises);
|
||||
async init() {
|
||||
await this.sdkLoadService.loadAndInit();
|
||||
await this.sshAgentService.init();
|
||||
this.nativeMessagingService.init();
|
||||
await this.migrationRunner.waitForCompletion(); // Desktop will run migrations in the main process
|
||||
this.encryptService.init(this.configService);
|
||||
|
||||
// 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.syncService.fullSync(true);
|
||||
await this.vaultTimeoutService.init(true);
|
||||
await (this.i18nService as I18nRendererService).init();
|
||||
(this.eventUploadService as EventUploadService).init(true);
|
||||
this.twoFactorService.init();
|
||||
this.notificationsService.startListening();
|
||||
const htmlEl = this.win.document.documentElement;
|
||||
htmlEl.classList.add("os_" + this.platformUtilsService.getDeviceString());
|
||||
this.themingService.applyThemeChangesTo(this.document);
|
||||
const accounts = await firstValueFrom(this.accountService.accounts$);
|
||||
const setUserKeyInMemoryPromises = [];
|
||||
for (const userId of Object.keys(accounts) as UserId[]) {
|
||||
// For each acct, we must await the process of setting the user key in memory
|
||||
// if the auto user key is set to avoid race conditions of any code trying to access
|
||||
// the user key from mem.
|
||||
setUserKeyInMemoryPromises.push(
|
||||
this.userAutoUnlockKeyService.setUserKeyInMemoryIfAutoUserKeySet(userId),
|
||||
);
|
||||
}
|
||||
await Promise.all(setUserKeyInMemoryPromises);
|
||||
|
||||
this.versionService.init();
|
||||
// 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.syncService.fullSync(true);
|
||||
await this.vaultTimeoutService.init(true);
|
||||
await (this.i18nService as I18nRendererService).init();
|
||||
(this.eventUploadService as EventUploadService).init(true);
|
||||
this.twoFactorService.init();
|
||||
this.notificationsService.startListening();
|
||||
const htmlEl = this.win.document.documentElement;
|
||||
htmlEl.classList.add("os_" + this.platformUtilsService.getDeviceString());
|
||||
this.themingService.applyThemeChangesTo(this.document);
|
||||
|
||||
const containerService = new ContainerService(this.keyService, this.encryptService);
|
||||
containerService.attachToGlobal(this.win);
|
||||
this.versionService.init();
|
||||
|
||||
await this.biometricMessageHandlerService.init();
|
||||
await this.autofillService.init();
|
||||
await this.autotypeService.init();
|
||||
};
|
||||
const containerService = new ContainerService(this.keyService, this.encryptService);
|
||||
containerService.attachToGlobal(this.win);
|
||||
|
||||
await this.biometricMessageHandlerService.init();
|
||||
await this.autofillService.init();
|
||||
await this.autotypeService.init();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { APP_INITIALIZER, NgModule } from "@angular/core";
|
||||
import { inject, NgModule, provideAppInitializer } from "@angular/core";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { Subject, merge } from "rxjs";
|
||||
|
||||
import { CollectionService, OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||
import { SetInitialPasswordService } from "@bitwarden/angular/auth/password-management/set-initial-password/set-initial-password.service.abstraction";
|
||||
import {
|
||||
DecentralizedInitService,
|
||||
initializableProvider,
|
||||
} from "@bitwarden/angular/platform/abstractions/decentralized-init.service";
|
||||
import { SafeProvider, safeProvider } from "@bitwarden/angular/platform/utils/safe-provider";
|
||||
import {
|
||||
SECURE_STORAGE,
|
||||
@@ -194,12 +198,10 @@ const safeProviders: SafeProvider[] = [
|
||||
safeProvider(BiometricMessageHandlerService),
|
||||
safeProvider(SearchBarService),
|
||||
safeProvider(DialogService),
|
||||
safeProvider({
|
||||
provide: APP_INITIALIZER as SafeInjectionToken<() => void>,
|
||||
useFactory: (initService: InitService) => initService.init(),
|
||||
deps: [InitService],
|
||||
multi: true,
|
||||
}),
|
||||
provideAppInitializer(() => {
|
||||
const initService = inject(DecentralizedInitService);
|
||||
return initService.init();
|
||||
}) as any,
|
||||
safeProvider({
|
||||
provide: RELOAD_CALLBACK,
|
||||
useValue: null,
|
||||
@@ -559,6 +561,7 @@ const safeProviders: SafeProvider[] = [
|
||||
LogService,
|
||||
],
|
||||
}),
|
||||
initializableProvider(InitService),
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { InjectionToken, Type } from "@angular/core";
|
||||
|
||||
import { SafeProvider } from "../utils/safe-provider";
|
||||
|
||||
/**
|
||||
* Services that implement Initializable can participate in decentralized initialization.
|
||||
* Each service declares its dependencies, and the DecentralizedInitService will execute
|
||||
@@ -33,6 +35,19 @@ export abstract class Initializable {
|
||||
*/
|
||||
export const INIT_SERVICES = new InjectionToken<Initializable[]>("INIT_SERVICES");
|
||||
|
||||
/**
|
||||
* Helper function to create a type-safe provider for an Initializable service.
|
||||
*
|
||||
* @param type The Initializable service class
|
||||
*/
|
||||
export function initializableProvider<T extends Type<Initializable>>(ctor: T) {
|
||||
return {
|
||||
provide: INIT_SERVICES,
|
||||
useExisting: ctor,
|
||||
multi: true,
|
||||
} as SafeProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Service responsible for coordinating decentralized initialization.
|
||||
* Discovers all registered Initializable services and executes their init()
|
||||
|
||||
Reference in New Issue
Block a user