From 850d593284e339aadbd8e7a9af28df2cb929806a Mon Sep 17 00:00:00 2001 From: Matt Gibson Date: Thu, 19 Dec 2024 16:23:08 -0800 Subject: [PATCH] create service to load sdk on application init --- .../browser/src/background/main.background.ts | 14 +- .../sdk/browser-sdk-client-factory.ts | 114 --------------- .../services/sdk/browser-sdk-load.service.ts | 134 ++++++++++++++++++ .../src/popup/services/init.service.ts | 3 + .../src/popup/services/services.module.ts | 17 ++- apps/web/src/app/core/core.module.ts | 8 ++ apps/web/src/app/core/init.service.ts | 3 + .../app/platform/web-sdk-client-factory.ts | 33 ----- .../src/app/platform/web-sdk-load.service.ts | 31 ++++ .../src/services/jslib-services.module.ts | 4 +- .../abstractions/sdk/sdk-load.service.ts | 3 + .../services/sdk/noop-sdk-load.service.ts | 8 ++ 12 files changed, 214 insertions(+), 158 deletions(-) create mode 100644 apps/browser/src/platform/services/sdk/browser-sdk-load.service.ts create mode 100644 apps/web/src/app/platform/web-sdk-load.service.ts create mode 100644 libs/common/src/platform/abstractions/sdk/sdk-load.service.ts create mode 100644 libs/common/src/platform/services/sdk/noop-sdk-load.service.ts diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 4c35dc39a3f..c558aefb0cc 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -93,6 +93,7 @@ import { KeyGenerationService as KeyGenerationServiceAbstraction } from "@bitwar import { LogService as LogServiceAbstraction } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { SdkPureClientFactory } from "@bitwarden/common/platform/abstractions/sdk/sdk-client-factory"; +import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service"; import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service"; import { StateService as StateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service"; import { @@ -262,6 +263,7 @@ import { BrowserSdkClientFactory, BrowserSdkPureClientFactory, } from "../platform/services/sdk/browser-sdk-client-factory"; +import { BrowserSdkLoadService } from "../platform/services/sdk/browser-sdk-load.service"; import { BackgroundTaskSchedulerService } from "../platform/services/task-scheduler/background-task-scheduler.service"; import { BackgroundMemoryStorageService } from "../platform/storage/background-memory-storage.service"; import { BrowserStorageServiceProvider } from "../platform/storage/browser-storage-service.provider"; @@ -381,6 +383,7 @@ export default class MainBackground { themeStateService: DefaultThemeStateService; autoSubmitLoginBackground: AutoSubmitLoginBackground; sdkService: SdkService; + sdkLoadService: SdkLoadService; pureSdkClientFactory: SdkPureClientFactory; cipherAuthorizationService: CipherAuthorizationService; inlineMenuFieldQualificationService: InlineMenuFieldQualificationService; @@ -499,7 +502,7 @@ export default class MainBackground { return derivedKey; }); - this.pureSdkClientFactory = new BrowserSdkPureClientFactory(this.logService); + this.pureSdkClientFactory = new BrowserSdkPureClientFactory(); this.largeObjectMemoryStorageForStateProviders = new LocalBackedSessionStorageService( sessionKey, this.storageService, @@ -744,8 +747,14 @@ export default class MainBackground { ); const sdkClientFactory = flagEnabled("sdk") - ? new BrowserSdkClientFactory(this.logService) + ? new BrowserSdkClientFactory() : new NoopSdkClientFactory(); + this.sdkLoadService = new BrowserSdkLoadService( + this.platformUtilsService, + this.apiService, + this.environmentService, + this.logService, + ); this.sdkService = new DefaultSdkService( sdkClientFactory, this.environmentService, @@ -1268,6 +1277,7 @@ export default class MainBackground { async bootstrap() { this.containerService.attachToGlobal(self); + await this.sdkLoadService.load(); // Only the "true" background should run migrations await this.stateService.init({ runMigrations: true }); diff --git a/apps/browser/src/platform/services/sdk/browser-sdk-client-factory.ts b/apps/browser/src/platform/services/sdk/browser-sdk-client-factory.ts index dc86fda2f6b..47b23505b0f 100644 --- a/apps/browser/src/platform/services/sdk/browser-sdk-client-factory.ts +++ b/apps/browser/src/platform/services/sdk/browser-sdk-client-factory.ts @@ -1,90 +1,13 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore -import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { SdkClientFactory, SdkPureClientFactory, } from "@bitwarden/common/platform/abstractions/sdk/sdk-client-factory"; -import { RecoverableSDKError } from "@bitwarden/common/platform/services/sdk/default-sdk.service"; import type { BitwardenClient, BitwardenPure } from "@bitwarden/sdk-internal"; -import { BrowserApi } from "../../browser/browser-api"; - -// https://stackoverflow.com/a/47880734 -const supported = (() => { - try { - if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") { - const module = new WebAssembly.Module( - Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00), - ); - if (module instanceof WebAssembly.Module) { - return new WebAssembly.Instance(module) instanceof WebAssembly.Instance; - } - } - } catch (e) { - // ignore - } - return false; -})(); - -// Due to using webpack as bundler, sync imports will return an async module. Since we do support -// top level awaits, we define a promise we can await in the `load` function. -let loadingPromise: Promise | undefined; - -// Manifest v3 does not support dynamic imports in the service worker. -if (BrowserApi.isManifestVersion(3)) { - if (supported) { - // eslint-disable-next-line no-console - console.debug("WebAssembly is supported in this environment"); - loadingPromise = import("./wasm"); - } else { - // eslint-disable-next-line no-console - console.debug("WebAssembly is not supported in this environment"); - loadingPromise = import("./fallback"); - } -} - -// Manifest v2 expects dynamic imports to prevent timing issues. -async function load() { - if (BrowserApi.isManifestVersion(3)) { - // Ensure we have loaded the module - await loadingPromise; - return; - } - - if (supported) { - // eslint-disable-next-line no-console - console.debug("WebAssembly is supported in this environment"); - await import("./wasm"); - } else { - // eslint-disable-next-line no-console - console.debug("WebAssembly is not supported in this environment"); - await import("./fallback"); - } -} - export class BrowserSdkPureClientFactory implements SdkPureClientFactory { - constructor(private readonly logService: LogService) {} async createPureSdkClient(): Promise { - const startTime = performance.now(); - try { - await loadWithTimeout(); - } catch (error) { - throw new Error(`Failed to load: ${error.message}`); - } - - const endTime = performance.now(); - const elapsed = Math.round((endTime - startTime) / 1000); - const instance = (globalThis as any).init_pure(); - this.logService.info("WASM pure SDK loaded in", Math.round(endTime - startTime), "ms"); - - // If it takes 3 seconds or more to load, we want to capture it. - if (elapsed >= 3) { - throw new RecoverableSDKError(instance, elapsed); - } - return instance; } } @@ -95,48 +18,11 @@ export class BrowserSdkPureClientFactory implements SdkPureClientFactory { * Works both in popup and service worker. */ export class BrowserSdkClientFactory implements SdkClientFactory { - constructor(private logService: LogService) {} - async createSdkClient( ...args: ConstructorParameters ): Promise { - const startTime = performance.now(); - try { - await loadWithTimeout(); - } catch (error) { - throw new Error(`Failed to load: ${error.message}`); - } - - const endTime = performance.now(); - const elapsed = Math.round((endTime - startTime) / 1000); - const instance = (globalThis as any).init_sdk(...args); - this.logService.info("WASM SDK loaded in", Math.round(endTime - startTime), "ms"); - - // If it takes 3 seconds or more to load, we want to capture it. - if (elapsed >= 3) { - throw new RecoverableSDKError(instance, elapsed); - } - return instance; } } - -const loadWithTimeout = async () => { - return new Promise((resolve, reject) => { - const timer = setTimeout(() => { - reject(new Error("Operation timed out after 10 second")); - }, 10000); - - load() - .then(() => { - clearTimeout(timer); - resolve(); - }) - .catch((error) => { - clearTimeout(timer); - reject(error); - }); - }); -}; diff --git a/apps/browser/src/platform/services/sdk/browser-sdk-load.service.ts b/apps/browser/src/platform/services/sdk/browser-sdk-load.service.ts new file mode 100644 index 00000000000..e21ed263932 --- /dev/null +++ b/apps/browser/src/platform/services/sdk/browser-sdk-load.service.ts @@ -0,0 +1,134 @@ +import { firstValueFrom } from "rxjs"; + +import { ApiService } from "@bitwarden/common/abstractions/api.service"; +import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; +import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service"; + +import { BrowserApi } from "../../browser/browser-api"; + +// https://stackoverflow.com/a/47880734 +const supported = (() => { + try { + if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") { + const module = new WebAssembly.Module( + Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00), + ); + if (module instanceof WebAssembly.Module) { + return new WebAssembly.Instance(module) instanceof WebAssembly.Instance; + } + } + } catch (e) { + // ignore + } + return false; +})(); + +// Due to using webpack as bundler, sync imports will return an async module. Since we do support +// top level awaits, we define a promise we can await in the `load` function. +let loadingPromise: Promise | undefined; + +// Manifest v3 does not support dynamic imports in the service worker. +if (BrowserApi.isManifestVersion(3)) { + if (supported) { + // eslint-disable-next-line no-console + console.debug("WebAssembly is supported in this environment"); + loadingPromise = import("./wasm"); + } else { + // eslint-disable-next-line no-console + console.debug("WebAssembly is not supported in this environment"); + loadingPromise = import("./fallback"); + } +} + +// Manifest v2 expects dynamic imports to prevent timing issues. +async function load() { + if (BrowserApi.isManifestVersion(3)) { + // Ensure we have loaded the module + await loadingPromise; + return; + } + + if (supported) { + // eslint-disable-next-line no-console + console.debug("WebAssembly is supported in this environment"); + await import("./wasm"); + } else { + // eslint-disable-next-line no-console + console.debug("WebAssembly is not supported in this environment"); + await import("./fallback"); + } +} + +const loadWithTimeout = async () => { + return new Promise((resolve, reject) => { + const timer = setTimeout(() => { + reject(new Error("Operation timed out after 10 second")); + }, 10000); + + load() + .then(() => { + clearTimeout(timer); + resolve(); + }) + .catch((error) => { + clearTimeout(timer); + reject(error); + }); + }); +}; + +export class BrowserSdkLoadService implements SdkLoadService { + constructor( + readonly platformUtilsService: PlatformUtilsService, + readonly apiService: ApiService, + readonly environmentService: EnvironmentService, + readonly logService: LogService, + ) {} + + async load(): Promise { + const startTime = performance.now(); + + try { + await loadWithTimeout(); + } catch (error) { + throw new Error(`Failed to load: ${(error as Error).message}`); + } + const endTime = performance.now(); + const elapsed = Math.round(endTime - startTime); + const message = `WASM SDK loaded in ${elapsed}ms`; + + this.logService.info(message); + + // If it takes 3 seconds or more to load, we want to capture it. + if (elapsed >= 3000) { + await this.logFailureToInitialize(message); + } + } + + private async logFailureToInitialize(message: string): Promise { + // Only log on cloud instances + if ( + this.platformUtilsService.isDev() || + !(await firstValueFrom(this.environmentService.environment$)).isCloud + ) { + return; + } + + return this.apiService.send( + "POST", + "/wasm-debug", + { + category: "sdk", + error: message, + }, + false, + false, + undefined, + (headers) => { + headers.append("SDK-Version", "1.0.0"); + }, + ); + } +} diff --git a/apps/browser/src/popup/services/init.service.ts b/apps/browser/src/popup/services/init.service.ts index 9e6471eaf28..958e8558671 100644 --- a/apps/browser/src/popup/services/init.service.ts +++ b/apps/browser/src/popup/services/init.service.ts @@ -6,6 +6,7 @@ import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService as LogServiceAbstraction } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { BrowserApi } from "../../platform/browser/browser-api"; @@ -19,11 +20,13 @@ export class InitService { private twoFactorService: TwoFactorService, private logService: LogServiceAbstraction, private themingService: AbstractThemingService, + private sdkLoadService: SdkLoadService, @Inject(DOCUMENT) private document: Document, ) {} init() { return async () => { + await this.sdkLoadService.load(); await this.stateService.init({ runMigrations: false }); // Browser background is responsible for migrations await this.i18nService.init(); this.twoFactorService.init(); diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts index 7f7c5b99971..858580d0807 100644 --- a/apps/browser/src/popup/services/services.module.ts +++ b/apps/browser/src/popup/services/services.module.ts @@ -74,6 +74,7 @@ import { SdkClientFactory, SdkPureClientFactory, } from "@bitwarden/common/platform/abstractions/sdk/sdk-client-factory"; +import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { AbstractStorageService, @@ -154,6 +155,7 @@ import { BrowserSdkClientFactory, BrowserSdkPureClientFactory, } from "../../platform/services/sdk/browser-sdk-client-factory"; +import { BrowserSdkLoadService } from "../../platform/services/sdk/browser-sdk-load.service"; import { ForegroundTaskSchedulerService } from "../../platform/services/task-scheduler/foreground-task-scheduler.service"; import { BrowserStorageServiceProvider } from "../../platform/storage/browser-storage-service.provider"; import { ForegroundMemoryStorageService } from "../../platform/storage/foreground-memory-storage.service"; @@ -587,18 +589,21 @@ const safeProviders: SafeProvider[] = [ useClass: ForegroundLockService, deps: [MessageSender, MessageListener], }), + safeProvider({ + provide: SdkLoadService, + useClass: BrowserSdkLoadService, + deps: [PlatformUtilsService, ApiService, EnvironmentService, LogService], + }), safeProvider({ provide: SdkClientFactory, - useFactory: (logService) => - flagEnabled("sdk") ? new BrowserSdkClientFactory(logService) : new NoopSdkClientFactory(), - deps: [LogService], + useFactory: () => + flagEnabled("sdk") ? new BrowserSdkClientFactory() : new NoopSdkClientFactory(), + deps: [], }), safeProvider({ provide: SdkPureClientFactory, useFactory: (logService) => - flagEnabled("sdk") - ? new BrowserSdkPureClientFactory(logService) - : new NoopSdkPureClientFactory(), + flagEnabled("sdk") ? new BrowserSdkPureClientFactory() : new NoopSdkPureClientFactory(), deps: [LogService], }), safeProvider({ diff --git a/apps/web/src/app/core/core.module.ts b/apps/web/src/app/core/core.module.ts index fa60520a3d3..9e8b49c503a 100644 --- a/apps/web/src/app/core/core.module.ts +++ b/apps/web/src/app/core/core.module.ts @@ -70,6 +70,7 @@ import { SdkClientFactory, SdkPureClientFactory, } from "@bitwarden/common/platform/abstractions/sdk/sdk-client-factory"; +import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service"; import { AbstractStorageService } from "@bitwarden/common/platform/abstractions/storage.service"; import { ThemeType } from "@bitwarden/common/platform/enums"; import { AppIdService as DefaultAppIdService } from "@bitwarden/common/platform/services/app-id.service"; @@ -81,6 +82,7 @@ import { NoopSdkClientFactory, NoopSdkPureClientFactory, } from "@bitwarden/common/platform/services/sdk/noop-sdk-client-factory"; +import { NoopSdkLoadService } from "@bitwarden/common/platform/services/sdk/noop-sdk-load.service"; import { StorageServiceProvider } from "@bitwarden/common/platform/services/storage-service.provider"; /* eslint-disable import/no-restricted-paths -- Implementation for memory storage */ import { GlobalStateProvider, StateProvider } from "@bitwarden/common/platform/state"; @@ -117,6 +119,7 @@ import { WebBiometricsService } from "../key-management/web-biometric.service"; import { WebEnvironmentService } from "../platform/web-environment.service"; import { WebMigrationRunner } from "../platform/web-migration-runner"; import { WebSdkClientFactory, WebSdkPureClientFactory } from "../platform/web-sdk-client-factory"; +import { WebSdkLoadService } from "../platform/web-sdk-load.service"; import { WebStorageServiceProvider } from "../platform/web-storage-service.provider"; import { EventService } from "./event.service"; @@ -294,6 +297,11 @@ const safeProviders: SafeProvider[] = [ useClass: DefaultCollectionAdminService, deps: [ApiService, KeyServiceAbstraction, EncryptService, CollectionService], }), + safeProvider({ + provide: SdkLoadService, + useClass: flagEnabled("sdk") ? WebSdkLoadService : NoopSdkLoadService, + deps: [], + }), safeProvider({ provide: SdkClientFactory, useClass: flagEnabled("sdk") ? WebSdkClientFactory : NoopSdkClientFactory, diff --git a/apps/web/src/app/core/init.service.ts b/apps/web/src/app/core/init.service.ts index b3e6d691f75..0d6063b4ac3 100644 --- a/apps/web/src/app/core/init.service.ts +++ b/apps/web/src/app/core/init.service.ts @@ -10,6 +10,7 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv import { TwoFactorService as TwoFactorServiceAbstraction } from "@bitwarden/common/auth/abstractions/two-factor.service"; import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service"; import { StateService as StateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service"; import { ContainerService } from "@bitwarden/common/platform/services/container.service"; import { UserAutoUnlockKeyService } from "@bitwarden/common/platform/services/user-auto-unlock-key.service"; @@ -35,11 +36,13 @@ export class InitService { private userAutoUnlockKeyService: UserAutoUnlockKeyService, private accountService: AccountService, private versionService: VersionService, + private sdkLoadService: SdkLoadService, @Inject(DOCUMENT) private document: Document, ) {} init() { return async () => { + await this.sdkLoadService.load(); await this.stateService.init(); const activeAccount = await firstValueFrom(this.accountService.activeAccount$); diff --git a/apps/web/src/app/platform/web-sdk-client-factory.ts b/apps/web/src/app/platform/web-sdk-client-factory.ts index 22b32a0d996..f76b94a2433 100644 --- a/apps/web/src/app/platform/web-sdk-client-factory.ts +++ b/apps/web/src/app/platform/web-sdk-client-factory.ts @@ -6,10 +6,6 @@ import * as sdk from "@bitwarden/sdk-internal"; export class WebSdkPureClientFactory implements SdkPureClientFactory { async createPureSdkClient(): Promise { - const module = await load(); - - (sdk as any).init(module); - return Promise.resolve(new sdk.BitwardenPure()); } } @@ -21,35 +17,6 @@ export class WebSdkClientFactory implements SdkClientFactory { async createSdkClient( ...args: ConstructorParameters ): Promise { - const module = await load(); - - (sdk as any).init(module); - return Promise.resolve(new sdk.BitwardenClient(...args)); } } - -// https://stackoverflow.com/a/47880734 -const supported = (() => { - try { - if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") { - const module = new WebAssembly.Module( - Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00), - ); - if (module instanceof WebAssembly.Module) { - return new WebAssembly.Instance(module) instanceof WebAssembly.Instance; - } - } - } catch (e) { - // ignore - } - return false; -})(); - -async function load() { - if (supported) { - return await import("@bitwarden/sdk-internal/bitwarden_wasm_internal_bg.wasm"); - } else { - return await import("@bitwarden/sdk-internal/bitwarden_wasm_internal_bg.wasm.js"); - } -} diff --git a/apps/web/src/app/platform/web-sdk-load.service.ts b/apps/web/src/app/platform/web-sdk-load.service.ts new file mode 100644 index 00000000000..f1f98736f2f --- /dev/null +++ b/apps/web/src/app/platform/web-sdk-load.service.ts @@ -0,0 +1,31 @@ +import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service"; +import * as sdk from "@bitwarden/sdk-internal"; + +// https://stackoverflow.com/a/47880734 +const supported = (() => { + try { + if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") { + const module = new WebAssembly.Module( + Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00), + ); + if (module instanceof WebAssembly.Module) { + return new WebAssembly.Instance(module) instanceof WebAssembly.Instance; + } + } + } catch (e) { + // ignore + } + return false; +})(); + +export class WebSdkLoadService implements SdkLoadService { + async load(): Promise { + let module: any; + if (supported) { + module = await import("@bitwarden/sdk-internal/bitwarden_wasm_internal_bg.wasm"); + } else { + module = await import("@bitwarden/sdk-internal/bitwarden_wasm_internal_bg.wasm.js"); + } + (sdk as any).init(module); + } +} diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index 87dc3ff4aa8..da01e31f91a 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -183,10 +183,8 @@ import { AppIdService } from "@bitwarden/common/platform/services/app-id.service import { ConfigApiService } from "@bitwarden/common/platform/services/config/config-api.service"; import { DefaultConfigService } from "@bitwarden/common/platform/services/config/default-config.service"; import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service"; -import { BulkEncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/bulk-encrypt.service.implementation"; -import { FallbackBulkEncryptService } from "@bitwarden/common/platform/services/cryptography/fallback-bulk-encrypt.service"; import { EncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/encrypt.service.implementation"; -import { MultithreadEncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/multithread-encrypt.service.implementation"; +import { FallbackBulkEncryptService } from "@bitwarden/common/platform/services/cryptography/fallback-bulk-encrypt.service"; import { DefaultBroadcasterService } from "@bitwarden/common/platform/services/default-broadcaster.service"; import { DefaultEnvironmentService } from "@bitwarden/common/platform/services/default-environment.service"; import { DefaultServerSettingsService } from "@bitwarden/common/platform/services/default-server-settings.service"; diff --git a/libs/common/src/platform/abstractions/sdk/sdk-load.service.ts b/libs/common/src/platform/abstractions/sdk/sdk-load.service.ts new file mode 100644 index 00000000000..16482e797b2 --- /dev/null +++ b/libs/common/src/platform/abstractions/sdk/sdk-load.service.ts @@ -0,0 +1,3 @@ +export abstract class SdkLoadService { + abstract load(): Promise; +} diff --git a/libs/common/src/platform/services/sdk/noop-sdk-load.service.ts b/libs/common/src/platform/services/sdk/noop-sdk-load.service.ts new file mode 100644 index 00000000000..fd6d4a8e4f0 --- /dev/null +++ b/libs/common/src/platform/services/sdk/noop-sdk-load.service.ts @@ -0,0 +1,8 @@ +// eslint-disable-next-line no-restricted-imports +import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service"; + +export class NoopSdkLoadService extends SdkLoadService { + async load() { + return; + } +}