Add more factories (#3381)

* Add more factories

Revert main.background factory usage.

We could still do this, but factories must init their services and so need
to be async, which is not compatible with initializing in constructors

* Fix conflicts
This commit is contained in:
Matt Gibson 2022-08-29 12:46:42 -06:00 committed by GitHub
parent 2c208edb98
commit a022c58b16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 570 additions and 92 deletions

View File

@ -47,6 +47,7 @@ import { AuditService } from "@bitwarden/common/services/audit.service";
import { AuthService } from "@bitwarden/common/services/auth.service";
import { CipherService } from "@bitwarden/common/services/cipher.service";
import { CollectionService } from "@bitwarden/common/services/collection.service";
import { ConsoleLogService } from "@bitwarden/common/services/consoleLog.service";
import { ContainerService } from "@bitwarden/common/services/container.service";
import { EncryptService } from "@bitwarden/common/services/encrypt.service";
import { EventService } from "@bitwarden/common/services/event.service";
@ -54,6 +55,7 @@ import { ExportService } from "@bitwarden/common/services/export.service";
import { FileUploadService } from "@bitwarden/common/services/fileUpload.service";
import { FolderApiService } from "@bitwarden/common/services/folder/folder-api.service";
import { KeyConnectorService } from "@bitwarden/common/services/keyConnector.service";
import { MemoryStorageService } from "@bitwarden/common/services/memoryStorage.service";
import { NotificationsService } from "@bitwarden/common/services/notifications.service";
import { OrganizationService } from "@bitwarden/common/services/organization.service";
import { PasswordGenerationService } from "@bitwarden/common/services/passwordGeneration.service";
@ -72,6 +74,7 @@ import { TwoFactorService } from "@bitwarden/common/services/twoFactor.service";
import { UserVerificationApiService } from "@bitwarden/common/services/userVerification/userVerification-api.service";
import { UserVerificationService } from "@bitwarden/common/services/userVerification/userVerification.service";
import { UsernameGenerationService } from "@bitwarden/common/services/usernameGeneration.service";
import { WebCryptoFunctionService } from "@bitwarden/common/services/webCryptoFunction.service";
import { BrowserApi } from "../browser/browserApi";
import { SafariApp } from "../browser/safariApp";
@ -82,11 +85,15 @@ import { StateService as StateServiceAbstraction } from "../services/abstraction
import AutofillService from "../services/autofill.service";
import { BrowserEnvironmentService } from "../services/browser-environment.service";
import { BrowserCryptoService } from "../services/browserCrypto.service";
import BrowserLocalStorageService from "../services/browserLocalStorage.service";
import BrowserMessagingService from "../services/browserMessaging.service";
import BrowserMessagingPrivateModeBackgroundService from "../services/browserMessagingPrivateModeBackground.service";
import BrowserPlatformUtilsService from "../services/browserPlatformUtils.service";
import { FolderService } from "../services/folders/folder.service";
import I18nService from "../services/i18n.service";
import { KeyGenerationService } from "../services/keyGeneration.service";
import { LocalBackedSessionStorageService } from "../services/localBackedSessionStorage.service";
import { StateService } from "../services/state.service";
import { VaultFilterService } from "../services/vaultFilter.service";
import VaultTimeoutService from "../services/vaultTimeout.service";
@ -97,17 +104,6 @@ import IconDetails from "./models/iconDetails";
import { NativeMessagingBackground } from "./nativeMessaging.background";
import NotificationBackground from "./notification.background";
import RuntimeBackground from "./runtime.background";
import { cryptoFunctionServiceFactory } from "./service_factories/crypto-function-service.factory";
import { encryptServiceFactory } from "./service_factories/encrypt-service.factory";
import { environmentServiceFactory } from "./service_factories/environment-service.factory";
import { logServiceFactory } from "./service_factories/log-service.factory";
import { stateMigrationServiceFactory } from "./service_factories/state-migration-service.factory";
import { stateServiceFactory } from "./service_factories/state-service.factory";
import {
diskStorageServiceFactory,
memoryStorageServiceFactory,
secureStorageServiceFactory,
} from "./service_factories/storage-service.factory";
import TabsBackground from "./tabs.background";
import WebRequestBackground from "./webRequest.background";
@ -199,40 +195,33 @@ export default class MainBackground {
const logoutCallback = async (expired: boolean, userId?: string) =>
await this.logout(expired, userId);
const services: Record<string, unknown> = {};
const factoryOptions = {
logServiceOptions: {
isDev: false,
},
cryptoFunctionServiceOptions: {
win: window,
},
stateMigrationServiceOptions: {
stateFactory: new StateFactory(GlobalState, Account),
},
stateServiceOptions: {
stateFactory: new StateFactory(GlobalState, Account),
},
};
this.messagingService = isPrivateMode
? new BrowserMessagingPrivateModeBackgroundService()
: new BrowserMessagingService();
this.logService = logServiceFactory(services, factoryOptions);
this.cryptoFunctionService = cryptoFunctionServiceFactory(services, factoryOptions);
this.storageService = diskStorageServiceFactory(services, factoryOptions);
this.secureStorageService = secureStorageServiceFactory(services, factoryOptions);
this.memoryStorageService = memoryStorageServiceFactory(services, {
...factoryOptions,
encryptServiceOptions: {
logMacFailures: false,
},
});
this.stateMigrationService = stateMigrationServiceFactory(services, factoryOptions);
this.stateService = stateServiceFactory(services, {
...factoryOptions,
encryptServiceOptions: { logMacFailures: false },
});
this.logService = new ConsoleLogService(false);
this.cryptoFunctionService = new WebCryptoFunctionService(window);
this.storageService = new BrowserLocalStorageService();
this.secureStorageService = new BrowserLocalStorageService();
this.memoryStorageService =
chrome.runtime.getManifest().manifest_version == 3
? new LocalBackedSessionStorageService(
new EncryptService(this.cryptoFunctionService, this.logService, false),
new KeyGenerationService(this.cryptoFunctionService)
)
: new MemoryStorageService();
this.stateMigrationService = new StateMigrationService(
this.storageService,
this.secureStorageService,
new StateFactory(GlobalState, Account)
);
this.stateService = new StateService(
this.storageService,
this.secureStorageService,
this.memoryStorageService,
this.logService,
this.stateMigrationService,
new StateFactory(GlobalState, Account)
);
this.platformUtilsService = new BrowserPlatformUtilsService(
this.messagingService,
(clipboardValue, clearMs) => {
@ -255,13 +244,7 @@ export default class MainBackground {
}
);
this.i18nService = new I18nService(BrowserApi.getUILanguage(window));
this.encryptService = encryptServiceFactory(services, {
...factoryOptions,
encryptServiceOptions: {
logMacFailures: true,
},
alwaysInitializeNewService: true,
}); // Update encrypt service with new instances
this.encryptService = new EncryptService(this.cryptoFunctionService, this.logService, true);
this.cryptoService = new BrowserCryptoService(
this.cryptoFunctionService,
this.encryptService,
@ -271,12 +254,7 @@ export default class MainBackground {
);
this.tokenService = new TokenService(this.stateService);
this.appIdService = new AppIdService(this.storageService);
this.environmentService = environmentServiceFactory(services, {
...factoryOptions,
encryptServiceOptions: {
logMacFailures: false,
},
});
this.environmentService = new BrowserEnvironmentService(this.stateService, this.logService);
this.apiService = new ApiService(
this.tokenService,
this.platformUtilsService,

View File

@ -0,0 +1,47 @@
import { ApiService as AbstractApiService } from "@bitwarden/common/abstractions/api.service";
import { ApiService } from "@bitwarden/common/services/api.service";
import { AppIdServiceInitOptions, appIdServiceFactory } from "./app-id-service.factory";
import {
environmentServiceFactory,
EnvironmentServiceInitOptions,
} from "./environment-service.factory";
import { CachedServices, factory, FactoryOptions } from "./factory-options";
import {
PlatformUtilsServiceInitOptions,
platformUtilsServiceFactory,
} from "./platform-utils-service.factory";
import { TokenServiceInitOptions, tokenServiceFactory } from "./token-service.factory";
type ApiServiceFactoryOptions = FactoryOptions & {
apiServiceOptions: {
logoutCallback: (expired: boolean) => Promise<void>;
customUserAgent?: string;
};
};
export type ApiServiceInitOptions = ApiServiceFactoryOptions &
TokenServiceInitOptions &
PlatformUtilsServiceInitOptions &
EnvironmentServiceInitOptions &
AppIdServiceInitOptions;
export function apiServiceFactory(
cache: { apiService?: AbstractApiService } & CachedServices,
opts: ApiServiceInitOptions
): Promise<AbstractApiService> {
return factory(
cache,
"apiService",
opts,
async () =>
new ApiService(
await tokenServiceFactory(cache, opts),
await platformUtilsServiceFactory(cache, opts),
await environmentServiceFactory(cache, opts),
await appIdServiceFactory(cache, opts),
opts.apiServiceOptions.logoutCallback,
opts.apiServiceOptions.customUserAgent
)
);
}

View File

@ -0,0 +1,23 @@
import { DiskStorageOptions } from "@koa/multer";
import { AppIdService as AbstractAppIdService } from "@bitwarden/common/abstractions/appId.service";
import { AppIdService } from "@bitwarden/common/services/appId.service";
import { FactoryOptions, CachedServices, factory } from "./factory-options";
import { diskStorageServiceFactory } from "./storage-service.factory";
type AppIdServiceFactoryOptions = FactoryOptions;
export type AppIdServiceInitOptions = AppIdServiceFactoryOptions & DiskStorageOptions;
export function appIdServiceFactory(
cache: { appIdService?: AbstractAppIdService } & CachedServices,
opts: AppIdServiceInitOptions
): Promise<AbstractAppIdService> {
return factory(
cache,
"appIdService",
opts,
async () => new AppIdService(await diskStorageServiceFactory(cache, opts))
);
}

View File

@ -0,0 +1,66 @@
import { AuthService as AbstractAuthService } from "@bitwarden/common/abstractions/auth.service";
import { AuthService } from "@bitwarden/common/services/auth.service";
import { apiServiceFactory, ApiServiceInitOptions } from "./api-service.factory";
import { appIdServiceFactory } from "./app-id-service.factory";
import { cryptoServiceFactory, CryptoServiceInitOptions } from "./crypto-service.factory";
import {
environmentServiceFactory,
EnvironmentServiceInitOptions,
} from "./environment-service.factory";
import { CachedServices, factory, FactoryOptions } from "./factory-options";
import { I18nServiceInitOptions, i18nServiceFactory } from "./i18n-service.factory";
import {
KeyConnectorServiceInitOptions,
keyConnectorServiceFactory,
} from "./key-connector-service.factory";
import { logServiceFactory, LogServiceInitOptions } from "./log-service.factory";
import { MessagingServiceInitOptions, messagingServiceFactory } from "./messaging-service.factory";
import {
PlatformUtilsServiceInitOptions,
platformUtilsServiceFactory,
} from "./platform-utils-service.factory";
import { stateServiceFactory, StateServiceInitOptions } from "./state-service.factory";
import { TokenServiceInitOptions, tokenServiceFactory } from "./token-service.factory";
import { TwoFactorServiceInitOptions, twoFactorServiceFactory } from "./two-factor-service.factory";
type AuthServiceFactoyOptions = FactoryOptions;
export type AuthServiceInitOptions = AuthServiceFactoyOptions &
CryptoServiceInitOptions &
ApiServiceInitOptions &
TokenServiceInitOptions &
PlatformUtilsServiceInitOptions &
MessagingServiceInitOptions &
LogServiceInitOptions &
KeyConnectorServiceInitOptions &
EnvironmentServiceInitOptions &
StateServiceInitOptions &
TwoFactorServiceInitOptions &
I18nServiceInitOptions;
export function authServiceFactory(
cache: { authService?: AbstractAuthService } & CachedServices,
opts: AuthServiceInitOptions
): Promise<AbstractAuthService> {
return factory(
cache,
"authService",
opts,
async () =>
new AuthService(
await cryptoServiceFactory(cache, opts),
await apiServiceFactory(cache, opts),
await tokenServiceFactory(cache, opts),
await appIdServiceFactory(cache, opts),
await platformUtilsServiceFactory(cache, opts),
await messagingServiceFactory(cache, opts),
await logServiceFactory(cache, opts),
await keyConnectorServiceFactory(cache, opts),
await environmentServiceFactory(cache, opts),
await stateServiceFactory(cache, opts),
await twoFactorServiceFactory(cache, opts),
await i18nServiceFactory(cache, opts)
)
);
}

View File

@ -0,0 +1,54 @@
import { CipherService as AbstractCipherService } from "@bitwarden/common/abstractions/cipher.service";
import { SearchService } from "@bitwarden/common/abstractions/search.service";
import { CipherService } from "@bitwarden/common/services/cipher.service";
import { apiServiceFactory, ApiServiceInitOptions } from "./api-service.factory";
import { cryptoServiceFactory, CryptoServiceInitOptions } from "./crypto-service.factory";
import { CachedServices, factory, FactoryOptions } from "./factory-options";
import {
FileUploadServiceInitOptions,
fileUploadServiceFactory,
} from "./file-upload-service.factory";
import { i18nServiceFactory, I18nServiceInitOptions } from "./i18n-service.factory";
import { logServiceFactory, LogServiceInitOptions } from "./log-service.factory";
import { SettingsServiceInitOptions, settingsServiceFactory } from "./settings-service.factory";
import { stateServiceFactory, StateServiceInitOptions } from "./state-service.factory";
type CipherServiceFactoryOptions = FactoryOptions & {
cipherServiceOptions?: {
searchServiceFactory?: () => SearchService;
};
};
export type CipherServiceInitOptions = CipherServiceFactoryOptions &
CryptoServiceInitOptions &
SettingsServiceInitOptions &
ApiServiceInitOptions &
FileUploadServiceInitOptions &
I18nServiceInitOptions &
LogServiceInitOptions &
StateServiceInitOptions;
export function cipherServiceFactory(
cache: { cipherService?: AbstractCipherService } & CachedServices,
opts: CipherServiceInitOptions
): Promise<AbstractCipherService> {
return factory(
cache,
"cipherService",
opts,
async () =>
new CipherService(
await cryptoServiceFactory(cache, opts),
await settingsServiceFactory(cache, opts),
await apiServiceFactory(cache, opts),
await fileUploadServiceFactory(cache, opts),
await i18nServiceFactory(cache, opts),
opts.cipherServiceOptions.searchServiceFactory === undefined
? () => cache.searchService
: opts.cipherServiceOptions.searchServiceFactory,
await logServiceFactory(cache, opts),
await stateServiceFactory(cache, opts)
)
);
}

View File

@ -14,7 +14,7 @@ export type CryptoFunctionServiceInitOptions = CryptoFunctionServiceFactoryOptio
export function cryptoFunctionServiceFactory(
cache: { cryptoFunctionService?: CryptoFunctionService } & CachedServices,
opts: CryptoFunctionServiceFactoryOptions
): CryptoFunctionService {
): Promise<CryptoFunctionService> {
return factory(
cache,
"cryptoFunctionService",

View File

@ -0,0 +1,43 @@
import { CryptoService as AbstractCryptoService } from "@bitwarden/common/abstractions/crypto.service";
import { CryptoService } from "@bitwarden/common/services/crypto.service";
import {
cryptoFunctionServiceFactory,
CryptoFunctionServiceInitOptions,
} from "./crypto-function-service.factory";
import { encryptServiceFactory, EncryptServiceInitOptions } from "./encrypt-service.factory";
import { FactoryOptions, CachedServices, factory } from "./factory-options";
import { logServiceFactory, LogServiceInitOptions } from "./log-service.factory";
import {
platformUtilsServiceFactory,
PlatformUtilsServiceInitOptions,
} from "./platform-utils-service.factory";
import { stateServiceFactory, StateServiceInitOptions } from "./state-service.factory";
type CryptoServiceFactoryOptions = FactoryOptions;
export type CryptoServiceInitOptions = CryptoServiceFactoryOptions &
CryptoFunctionServiceInitOptions &
EncryptServiceInitOptions &
PlatformUtilsServiceInitOptions &
LogServiceInitOptions &
StateServiceInitOptions;
export function cryptoServiceFactory(
cache: { cryptoService?: AbstractCryptoService } & CachedServices,
opts: CryptoServiceInitOptions
): Promise<AbstractCryptoService> {
return factory(
cache,
"cryptoService",
opts,
async () =>
new CryptoService(
await cryptoFunctionServiceFactory(cache, opts),
await encryptServiceFactory(cache, opts),
await platformUtilsServiceFactory(cache, opts),
await logServiceFactory(cache, opts),
await stateServiceFactory(cache, opts)
)
);
}

View File

@ -20,15 +20,15 @@ export type EncryptServiceInitOptions = EncryptServiceFactoryOptions &
export function encryptServiceFactory(
cache: { encryptService?: EncryptService } & CachedServices,
opts: EncryptServiceInitOptions
): EncryptService {
): Promise<EncryptService> {
return factory(
cache,
"encryptService",
opts,
() =>
async () =>
new EncryptService(
cryptoFunctionServiceFactory(cache, opts),
logServiceFactory(cache, opts),
await cryptoFunctionServiceFactory(cache, opts),
await logServiceFactory(cache, opts),
opts.encryptServiceOptions.logMacFailures
)
);

View File

@ -16,15 +16,15 @@ export type EnvironmentServiceInitOptions = EnvironmentServiceFactoryOptions &
export function environmentServiceFactory(
cache: { environmentService?: BrowserEnvironmentService } & CachedServices,
opts: EnvironmentServiceInitOptions
): BrowserEnvironmentService {
): Promise<BrowserEnvironmentService> {
return factory(
cache,
"environmentService",
opts,
() =>
async () =>
new BrowserEnvironmentService(
stateServiceFactory(cache, opts),
logServiceFactory(cache, opts)
await stateServiceFactory(cache, opts),
await logServiceFactory(cache, opts)
)
);
}

View File

@ -6,14 +6,20 @@ export type FactoryOptions = {
[optionsKey: string]: unknown;
};
export function factory<
export async function factory<
TCache extends CachedServices,
TName extends keyof TCache,
TOpts extends FactoryOptions
>(cachedServices: TCache, name: TName, opts: TOpts, factory: () => TCache[TName]): TCache[TName] {
>(
cachedServices: TCache,
name: TName,
opts: TOpts,
factory: () => TCache[TName] | Promise<TCache[TName]>
): Promise<TCache[TName]> {
let instance = cachedServices[name];
if (opts.alwaysInitializeNewService || !instance) {
instance = factory();
const instanceOrPromise = factory();
instance = instanceOrPromise instanceof Promise ? await instanceOrPromise : instanceOrPromise;
}
if (!opts.doNotStoreInitializedService) {

View File

@ -0,0 +1,28 @@
import { FileUploadService as AbstractFileUploadService } from "@bitwarden/common/abstractions/fileUpload.service";
import { FileUploadService } from "@bitwarden/common/services/fileUpload.service";
import { apiServiceFactory, ApiServiceInitOptions } from "./api-service.factory";
import { FactoryOptions, CachedServices, factory } from "./factory-options";
import { logServiceFactory, LogServiceInitOptions } from "./log-service.factory";
type FileUploadServiceFactoyOptions = FactoryOptions;
export type FileUploadServiceInitOptions = FileUploadServiceFactoyOptions &
LogServiceInitOptions &
ApiServiceInitOptions;
export function fileUploadServiceFactory(
cache: { fileUploadService?: AbstractFileUploadService } & CachedServices,
opts: FileUploadServiceInitOptions
): Promise<AbstractFileUploadService> {
return factory(
cache,
"fileUploadService",
opts,
async () =>
new FileUploadService(
await logServiceFactory(cache, opts),
await apiServiceFactory(cache, opts)
)
);
}

View File

@ -0,0 +1,30 @@
import { I18nService as AbstractI18nService } from "@bitwarden/common/abstractions/i18n.service";
import { I18nService as BaseI18nService } from "@bitwarden/common/services/i18n.service";
import I18nService from "../../services/i18n.service";
import { FactoryOptions, CachedServices, factory } from "./factory-options";
type I18nServiceFactoryOptions = FactoryOptions & {
i18nServiceOptions: {
systemLanguage: string;
};
};
export type I18nServiceInitOptions = I18nServiceFactoryOptions;
export async function i18nServiceFactory(
cache: { i18nService?: AbstractI18nService } & CachedServices,
opts: I18nServiceInitOptions
): Promise<AbstractI18nService> {
const service = await factory(
cache,
"i18nService",
opts,
() => new I18nService(opts.i18nServiceOptions.systemLanguage)
);
if (!(service as BaseI18nService as any).inited) {
await (service as BaseI18nService).init();
}
return service;
}

View File

@ -0,0 +1,54 @@
import { KeyConnectorService as AbstractKeyConnectorService } from "@bitwarden/common/abstractions/keyConnector.service";
import { KeyConnectorService } from "@bitwarden/common/services/keyConnector.service";
import { apiServiceFactory, ApiServiceInitOptions } from "./api-service.factory";
import {
cryptoFunctionServiceFactory,
CryptoFunctionServiceInitOptions,
} from "./crypto-function-service.factory";
import { CryptoServiceInitOptions, cryptoServiceFactory } from "./crypto-service.factory";
import { FactoryOptions, CachedServices, factory } from "./factory-options";
import { logServiceFactory, LogServiceInitOptions } from "./log-service.factory";
import {
OrganizationServiceInitOptions,
organizationServiceFactory,
} from "./organization-service.factory";
import { stateServiceFactory, StateServiceInitOptions } from "./state-service.factory";
import { tokenServiceFactory, TokenServiceInitOptions } from "./token-service.factory";
type KeyConnectorServiceFactoryOptions = FactoryOptions & {
keyConnectorServiceOptions: {
logoutCallback: (expired: boolean, userId?: string) => Promise<void>;
};
};
export type KeyConnectorServiceInitOptions = KeyConnectorServiceFactoryOptions &
StateServiceInitOptions &
CryptoServiceInitOptions &
ApiServiceInitOptions &
TokenServiceInitOptions &
LogServiceInitOptions &
OrganizationServiceInitOptions &
CryptoFunctionServiceInitOptions;
export function keyConnectorServiceFactory(
cache: { keyConnectorService?: AbstractKeyConnectorService } & CachedServices,
opts: KeyConnectorServiceInitOptions
): Promise<AbstractKeyConnectorService> {
return factory(
cache,
"keyConnectorService",
opts,
async () =>
new KeyConnectorService(
await stateServiceFactory(cache, opts),
await cryptoServiceFactory(cache, opts),
await apiServiceFactory(cache, opts),
await tokenServiceFactory(cache, opts),
await logServiceFactory(cache, opts),
await organizationServiceFactory(cache, opts),
await cryptoFunctionServiceFactory(cache, opts),
opts.keyConnectorServiceOptions.logoutCallback
)
);
}

View File

@ -14,11 +14,11 @@ export type KeyGenerationServiceInitOptions = KeyGenerationServiceFactoryOptions
export function keyGenerationServiceFactory(
cache: { keyGenerationService?: KeyGenerationService } & CachedServices,
opts: KeyGenerationServiceInitOptions
): KeyGenerationService {
): Promise<KeyGenerationService> {
return factory(
cache,
"keyGenerationService",
opts,
() => new KeyGenerationService(cryptoFunctionServiceFactory(cache, opts))
async () => new KeyGenerationService(await cryptoFunctionServiceFactory(cache, opts))
);
}

View File

@ -16,7 +16,7 @@ export type LogServiceInitOptions = LogServiceFactoryOptions;
export function logServiceFactory(
cache: { logService?: LogService } & CachedServices,
opts: LogServiceInitOptions
): LogService {
): Promise<LogService> {
return factory(
cache,
"logService",

View File

@ -0,0 +1,16 @@
import { MessagingService as AbstractMessagingService } from "@bitwarden/common/abstractions/messaging.service";
import BrowserMessagingService from "../../services/browserMessaging.service";
import { CachedServices, factory, FactoryOptions } from "./factory-options";
type MessagingServiceFactoryOptions = FactoryOptions;
export type MessagingServiceInitOptions = MessagingServiceFactoryOptions;
export function messagingServiceFactory(
cache: { messagingService?: AbstractMessagingService } & CachedServices,
opts: MessagingServiceInitOptions
): Promise<AbstractMessagingService> {
return factory(cache, "messagingService", opts, () => new BrowserMessagingService());
}

View File

@ -0,0 +1,22 @@
import { OrganizationService as AbstractOrganizationService } from "@bitwarden/common/abstractions/organization.service";
import { OrganizationService } from "@bitwarden/common/services/organization.service";
import { FactoryOptions, CachedServices, factory } from "./factory-options";
import { stateServiceFactory, StateServiceInitOptions } from "./state-service.factory";
type OrganizationServiceFactoryOptions = FactoryOptions;
export type OrganizationServiceInitOptions = OrganizationServiceFactoryOptions &
StateServiceInitOptions;
export function organizationServiceFactory(
cache: { organizationService?: AbstractOrganizationService } & CachedServices,
opts: OrganizationServiceInitOptions
): Promise<AbstractOrganizationService> {
return factory(
cache,
"organizationService",
opts,
async () => new OrganizationService(await stateServiceFactory(cache, opts))
);
}

View File

@ -0,0 +1,34 @@
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import BrowserPlatformUtilsService from "../../services/browserPlatformUtils.service";
import { CachedServices, factory, FactoryOptions } from "./factory-options";
import { MessagingServiceInitOptions, messagingServiceFactory } from "./messaging-service.factory";
type PlatformUtilsServiceFactoryOptions = FactoryOptions & {
platformUtilsServiceOptions: {
clipboardWriteCallback: (clipboardValue: string, clearMs: number) => Promise<void>;
biometricCallback: () => Promise<boolean>;
win: Window & typeof globalThis;
};
};
export type PlatformUtilsServiceInitOptions = PlatformUtilsServiceFactoryOptions &
MessagingServiceInitOptions;
export function platformUtilsServiceFactory(
cache: { platformUtilsService?: PlatformUtilsService } & CachedServices,
opts: PlatformUtilsServiceInitOptions
): Promise<PlatformUtilsService> {
return factory(
cache,
"platformUtilsService",
opts,
async () =>
new BrowserPlatformUtilsService(
await messagingServiceFactory(cache, opts),
opts.platformUtilsServiceOptions.clipboardWriteCallback,
opts.platformUtilsServiceOptions.biometricCallback
)
);
}

View File

@ -0,0 +1,21 @@
import { SettingsService as AbstractSettingsService } from "@bitwarden/common/abstractions/settings.service";
import { SettingsService } from "@bitwarden/common/services/settings.service";
import { FactoryOptions, CachedServices, factory } from "./factory-options";
import { stateServiceFactory, StateServiceInitOptions } from "./state-service.factory";
type SettingsServiceFactoryOptions = FactoryOptions;
export type SettingsServiceInitOptions = SettingsServiceFactoryOptions & StateServiceInitOptions;
export function settingsServiceFactory(
cache: { settingsService?: AbstractSettingsService } & CachedServices,
opts: SettingsServiceInitOptions
): Promise<AbstractSettingsService> {
return factory(
cache,
"settingsService",
opts,
async () => new SettingsService(await stateServiceFactory(cache, opts))
);
}

View File

@ -25,15 +25,15 @@ export type StateMigrationServiceInitOptions = StateMigrationServiceFactoryOptio
export function stateMigrationServiceFactory(
cache: { stateMigrationService?: StateMigrationService } & CachedServices,
opts: StateMigrationServiceInitOptions
): StateMigrationService {
): Promise<StateMigrationService> {
return factory(
cache,
"stateMigrationService",
opts,
() =>
async () =>
new StateMigrationService(
diskStorageServiceFactory(cache, opts),
secureStorageServiceFactory(cache, opts),
await diskStorageServiceFactory(cache, opts),
await secureStorageServiceFactory(cache, opts),
opts.stateMigrationServiceOptions.stateFactory
)
);

View File

@ -33,23 +33,25 @@ export type StateServiceInitOptions = StateServiceFactoryOptions &
LogServiceInitOptions &
StateMigrationServiceInitOptions;
export function stateServiceFactory(
export async function stateServiceFactory(
cache: { stateService?: StateService } & CachedServices,
opts: StateServiceInitOptions
): StateService {
return factory(
): Promise<StateService> {
const service = await factory(
cache,
"stateService",
opts,
() =>
new StateService(
diskStorageServiceFactory(cache, opts),
secureStorageServiceFactory(cache, opts),
memoryStorageServiceFactory(cache, opts),
logServiceFactory(cache, opts),
stateMigrationServiceFactory(cache, opts),
async () =>
await new StateService(
await diskStorageServiceFactory(cache, opts),
await secureStorageServiceFactory(cache, opts),
await memoryStorageServiceFactory(cache, opts),
await logServiceFactory(cache, opts),
await stateMigrationServiceFactory(cache, opts),
opts.stateServiceOptions.stateFactory,
opts.stateServiceOptions.useAccountCache
)
);
service.init();
return service;
}

View File

@ -22,26 +22,26 @@ export type MemoryStorageServiceInitOptions = StorageServiceFactoryOptions &
export function diskStorageServiceFactory(
cache: { diskStorageService?: AbstractStorageService } & CachedServices,
opts: DiskStorageServiceInitOptions
): AbstractStorageService {
): Promise<AbstractStorageService> {
return factory(cache, "diskStorageService", opts, () => new BrowserLocalStorageService());
}
export function secureStorageServiceFactory(
cache: { secureStorageService?: AbstractStorageService } & CachedServices,
opts: SecureStorageServiceInitOptions
): AbstractStorageService {
): Promise<AbstractStorageService> {
return factory(cache, "secureStorageService", opts, () => new BrowserLocalStorageService());
}
export function memoryStorageServiceFactory(
cache: { memoryStorageService?: AbstractStorageService } & CachedServices,
opts: MemoryStorageServiceInitOptions
): AbstractStorageService {
return factory(cache, "memoryStorageService", opts, () => {
): Promise<AbstractStorageService> {
return factory(cache, "memoryStorageService", opts, async () => {
if (chrome.runtime.getManifest().manifest_version == 3) {
return new LocalBackedSessionStorageService(
encryptServiceFactory(cache, opts),
keyGenerationServiceFactory(cache, opts)
await encryptServiceFactory(cache, opts),
await keyGenerationServiceFactory(cache, opts)
);
}
return new MemoryStorageService();

View File

@ -0,0 +1,21 @@
import { TokenService as AbstractTokenService } from "@bitwarden/common/abstractions/token.service";
import { TokenService } from "@bitwarden/common/services/token.service";
import { CachedServices, factory, FactoryOptions } from "./factory-options";
import { stateServiceFactory, StateServiceInitOptions } from "./state-service.factory";
type TokenServiceFactoryOptions = FactoryOptions;
export type TokenServiceInitOptions = TokenServiceFactoryOptions & StateServiceInitOptions;
export function tokenServiceFactory(
cache: { tokenService?: AbstractTokenService } & CachedServices,
opts: TokenServiceInitOptions
): Promise<AbstractTokenService> {
return factory(
cache,
"tokenService",
opts,
async () => new TokenService(await stateServiceFactory(cache, opts))
);
}

View File

@ -0,0 +1,33 @@
import { TwoFactorService as AbstractTwoFactorService } from "@bitwarden/common/abstractions/twoFactor.service";
import { TwoFactorService } from "@bitwarden/common/services/twoFactor.service";
import { FactoryOptions, CachedServices, factory } from "./factory-options";
import { I18nServiceInitOptions, i18nServiceFactory } from "./i18n-service.factory";
import {
platformUtilsServiceFactory,
PlatformUtilsServiceInitOptions,
} from "./platform-utils-service.factory";
type TwoFactorServiceFactoryOptions = FactoryOptions;
export type TwoFactorServiceInitOptions = TwoFactorServiceFactoryOptions &
I18nServiceInitOptions &
PlatformUtilsServiceInitOptions;
export async function twoFactorServiceFactory(
cache: { twoFactorService?: AbstractTwoFactorService } & CachedServices,
opts: TwoFactorServiceInitOptions
): Promise<AbstractTwoFactorService> {
const service = await factory(
cache,
"twoFactorService",
opts,
async () =>
new TwoFactorService(
await i18nServiceFactory(cache, opts),
await platformUtilsServiceFactory(cache, opts)
)
);
await service.init();
return service;
}

View File

@ -5,7 +5,7 @@ import { environmentServiceFactory } from "../background/service_factories/envir
import { BrowserApi } from "../browser/browserApi";
import { Account } from "../models/account";
export function onInstallListener(details: chrome.runtime.InstalledDetails) {
export async function onInstallListener(details: chrome.runtime.InstalledDetails) {
const cache = {};
const opts = {
encryptServiceOptions: {
@ -24,7 +24,7 @@ export function onInstallListener(details: chrome.runtime.InstalledDetails) {
stateFactory: new StateFactory(GlobalState, Account),
},
};
const environmentService = environmentServiceFactory(cache, opts);
const environmentService = await environmentServiceFactory(cache, opts);
setTimeout(async () => {
if (details.reason != null && details.reason === "install") {