1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-11 22:03:36 +00:00

[PM-16217] Remove wasm timeout (#12476)

Remove the WASM timeout logic and supported$.
This commit is contained in:
Oscar Hinton
2024-12-20 13:54:52 +01:00
committed by GitHub
parent 8c1f1a2e49
commit 8caadacfbc
10 changed files with 7 additions and 222 deletions

View File

@@ -739,7 +739,6 @@ export default class MainBackground {
this.accountService, this.accountService,
this.kdfConfigService, this.kdfConfigService,
this.keyService, this.keyService,
this.apiService,
); );
this.passwordStrengthService = new PasswordStrengthService(); this.passwordStrengthService = new PasswordStrengthService();
@@ -1313,23 +1312,6 @@ export default class MainBackground {
await this.initOverlayAndTabsBackground(); await this.initOverlayAndTabsBackground();
if (flagEnabled("sdk")) {
// Warn if the SDK for some reason can't be initialized
let supported = false;
let error: Error;
try {
supported = await firstValueFrom(this.sdkService.supported$);
} catch (e) {
error = e;
}
if (!supported) {
this.sdkService
.failedToInitialize("background", error)
.catch((e) => this.logService.error(e));
}
}
return new Promise<void>((resolve) => { return new Promise<void>((resolve) => {
setTimeout(async () => { setTimeout(async () => {
await this.refreshBadge(); await this.refreshBadge();

View File

@@ -2,7 +2,6 @@
// @ts-strict-ignore // @ts-strict-ignore
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { SdkClientFactory } from "@bitwarden/common/platform/abstractions/sdk/sdk-client-factory"; import { SdkClientFactory } from "@bitwarden/common/platform/abstractions/sdk/sdk-client-factory";
import { RecoverableSDKError } from "@bitwarden/common/platform/services/sdk/default-sdk.service";
import type { BitwardenClient } from "@bitwarden/sdk-internal"; import type { BitwardenClient } from "@bitwarden/sdk-internal";
import { BrowserApi } from "../../browser/browser-api"; import { BrowserApi } from "../../browser/browser-api";
@@ -72,42 +71,14 @@ export class BrowserSdkClientFactory implements SdkClientFactory {
...args: ConstructorParameters<typeof BitwardenClient> ...args: ConstructorParameters<typeof BitwardenClient>
): Promise<BitwardenClient> { ): Promise<BitwardenClient> {
const startTime = performance.now(); const startTime = performance.now();
try { await load();
await loadWithTimeout();
} catch (error) {
throw new Error(`Failed to load: ${error.message}`);
}
const endTime = performance.now(); const endTime = performance.now();
const elapsed = Math.round((endTime - startTime) / 1000);
const instance = (globalThis as any).init_sdk(...args); const instance = (globalThis as any).init_sdk(...args);
this.logService.info("WASM SDK loaded in", Math.round(endTime - startTime), "ms"); 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; return instance;
} }
} }
const loadWithTimeout = async () => {
return new Promise<void>((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);
});
});
};

View File

@@ -1,7 +1,6 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { ChangeDetectorRef, Component, NgZone, OnDestroy, OnInit, inject } from "@angular/core"; import { ChangeDetectorRef, Component, NgZone, OnDestroy, OnInit, inject } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { NavigationEnd, Router, RouterOutlet } from "@angular/router"; import { NavigationEnd, Router, RouterOutlet } from "@angular/router";
import { Subject, takeUntil, firstValueFrom, concatMap, filter, tap } from "rxjs"; import { Subject, takeUntil, firstValueFrom, concatMap, filter, tap } from "rxjs";
@@ -11,9 +10,7 @@ import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { AnimationControlService } from "@bitwarden/common/platform/abstractions/animation-control.service"; import { AnimationControlService } from "@bitwarden/common/platform/abstractions/animation-control.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { MessageListener } from "@bitwarden/common/platform/messaging"; import { MessageListener } from "@bitwarden/common/platform/messaging";
import { UserId } from "@bitwarden/common/types/guid"; import { UserId } from "@bitwarden/common/types/guid";
@@ -25,7 +22,6 @@ import {
ToastService, ToastService,
} from "@bitwarden/components"; } from "@bitwarden/components";
import { flagEnabled } from "../platform/flags";
import { PopupCompactModeService } from "../platform/popup/layout/popup-compact-mode.service"; import { PopupCompactModeService } from "../platform/popup/layout/popup-compact-mode.service";
import { PopupWidthService } from "../platform/popup/layout/popup-width.service"; import { PopupWidthService } from "../platform/popup/layout/popup-width.service";
import { PopupViewCacheService } from "../platform/popup/view-cache/popup-view-cache.service"; import { PopupViewCacheService } from "../platform/popup/view-cache/popup-view-cache.service";
@@ -72,31 +68,7 @@ export class AppComponent implements OnInit, OnDestroy {
private toastService: ToastService, private toastService: ToastService,
private accountService: AccountService, private accountService: AccountService,
private animationControlService: AnimationControlService, private animationControlService: AnimationControlService,
private logService: LogService, ) {}
private sdkService: SdkService,
) {
if (flagEnabled("sdk")) {
// Warn if the SDK for some reason can't be initialized
this.sdkService.supported$.pipe(takeUntilDestroyed()).subscribe({
next: (supported) => {
if (!supported) {
this.logService.debug("SDK is not supported");
this.sdkService
.failedToInitialize("popup", undefined)
.catch((e) => this.logService.error(e));
} else {
this.logService.debug("SDK is supported");
}
},
error: (e: unknown) => {
this.sdkService
.failedToInitialize("popup", e as Error)
.catch((e) => this.logService.error(e));
this.logService.error(e);
},
});
}
}
async ngOnInit() { async ngOnInit() {
initPopupClosedListener(); initPopupClosedListener();

View File

@@ -550,7 +550,6 @@ export class ServiceContainer {
this.accountService, this.accountService,
this.kdfConfigService, this.kdfConfigService,
this.keyService, this.keyService,
this.apiService,
customUserAgent, customUserAgent,
); );
@@ -864,19 +863,5 @@ export class ServiceContainer {
} }
this.inited = true; this.inited = true;
if (flagEnabled("sdk")) {
// Warn if the SDK for some reason can't be initialized
let supported = false;
try {
supported = await firstValueFrom(this.sdkService.supported$);
} catch (e) {
// Do nothing.
}
if (!supported) {
this.sdkService.failedToInitialize("cli").catch((e) => this.logService.error(e));
}
}
} }
} }

View File

@@ -10,19 +10,8 @@ import {
ViewChild, ViewChild,
ViewContainerRef, ViewContainerRef,
} from "@angular/core"; } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { Router } from "@angular/router"; import { Router } from "@angular/router";
import { import { filter, firstValueFrom, map, Subject, takeUntil, timeout, withLatestFrom } from "rxjs";
catchError,
filter,
firstValueFrom,
map,
of,
Subject,
takeUntil,
timeout,
withLatestFrom,
} from "rxjs";
import { CollectionService } from "@bitwarden/admin-console/common"; import { CollectionService } from "@bitwarden/admin-console/common";
import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref"; import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref";
@@ -52,7 +41,6 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { SystemService } from "@bitwarden/common/platform/abstractions/system.service"; import { SystemService } from "@bitwarden/common/platform/abstractions/system.service";
import { clearCaches } from "@bitwarden/common/platform/misc/sequentialize"; import { clearCaches } from "@bitwarden/common/platform/misc/sequentialize";
@@ -70,7 +58,6 @@ import { KeyService, BiometricStateService } from "@bitwarden/key-management";
import { DeleteAccountComponent } from "../auth/delete-account.component"; import { DeleteAccountComponent } from "../auth/delete-account.component";
import { MenuAccount, MenuUpdateRequest } from "../main/menu/menu.updater"; import { MenuAccount, MenuUpdateRequest } from "../main/menu/menu.updater";
import { flagEnabled } from "../platform/flags";
import { PremiumComponent } from "../vault/app/accounts/premium.component"; import { PremiumComponent } from "../vault/app/accounts/premium.component";
import { FolderAddEditComponent } from "../vault/app/vault/folder-add-edit.component"; import { FolderAddEditComponent } from "../vault/app/vault/folder-add-edit.component";
@@ -167,28 +154,8 @@ export class AppComponent implements OnInit, OnDestroy {
private biometricStateService: BiometricStateService, private biometricStateService: BiometricStateService,
private stateEventRunnerService: StateEventRunnerService, private stateEventRunnerService: StateEventRunnerService,
private accountService: AccountService, private accountService: AccountService,
private sdkService: SdkService,
private organizationService: OrganizationService, private organizationService: OrganizationService,
) { ) {}
if (flagEnabled("sdk")) {
// Warn if the SDK for some reason can't be initialized
this.sdkService.supported$
.pipe(
takeUntilDestroyed(),
catchError(() => {
return of(false);
}),
)
.subscribe((supported) => {
if (!supported) {
this.logService.debug("SDK is not supported");
this.sdkService.failedToInitialize("desktop").catch((e) => this.logService.error(e));
} else {
this.logService.debug("SDK is supported");
}
});
}
}
ngOnInit() { ngOnInit() {
this.accountService.activeAccount$.pipe(takeUntil(this.destroy$)).subscribe((account) => { this.accountService.activeAccount$.pipe(takeUntil(this.destroy$)).subscribe((account) => {

View File

@@ -2,10 +2,9 @@
// @ts-strict-ignore // @ts-strict-ignore
import { DOCUMENT } from "@angular/common"; import { DOCUMENT } from "@angular/common";
import { Component, Inject, NgZone, OnDestroy, OnInit } from "@angular/core"; import { Component, Inject, NgZone, OnDestroy, OnInit } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { NavigationEnd, Router } from "@angular/router"; import { NavigationEnd, Router } from "@angular/router";
import * as jq from "jquery"; import * as jq from "jquery";
import { Subject, filter, firstValueFrom, map, takeUntil, timeout, catchError, of } from "rxjs"; import { Subject, filter, firstValueFrom, map, takeUntil, timeout } from "rxjs";
import { CollectionService } from "@bitwarden/admin-console/common"; import { CollectionService } from "@bitwarden/admin-console/common";
import { EventUploadService } from "@bitwarden/common/abstractions/event/event-upload.service"; import { EventUploadService } from "@bitwarden/common/abstractions/event/event-upload.service";
@@ -22,9 +21,7 @@ import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-managemen
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { StateEventRunnerService } from "@bitwarden/common/platform/state"; import { StateEventRunnerService } from "@bitwarden/common/platform/state";
import { SyncService } from "@bitwarden/common/platform/sync"; import { SyncService } from "@bitwarden/common/platform/sync";
@@ -34,8 +31,6 @@ import { DialogService, ToastService } from "@bitwarden/components";
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
import { KeyService, BiometricStateService } from "@bitwarden/key-management"; import { KeyService, BiometricStateService } from "@bitwarden/key-management";
import { flagEnabled } from "../utils/flags";
import { PolicyListService } from "./admin-console/core/policy-list.service"; import { PolicyListService } from "./admin-console/core/policy-list.service";
import { import {
DisableSendPolicy, DisableSendPolicy,
@@ -93,29 +88,8 @@ export class AppComponent implements OnDestroy, OnInit {
private stateEventRunnerService: StateEventRunnerService, private stateEventRunnerService: StateEventRunnerService,
private organizationService: InternalOrganizationServiceAbstraction, private organizationService: InternalOrganizationServiceAbstraction,
private accountService: AccountService, private accountService: AccountService,
private logService: LogService,
private sdkService: SdkService,
private processReloadService: ProcessReloadServiceAbstraction, private processReloadService: ProcessReloadServiceAbstraction,
) { ) {}
if (flagEnabled("sdk")) {
// Warn if the SDK for some reason can't be initialized
this.sdkService.supported$
.pipe(
takeUntilDestroyed(),
catchError(() => {
return of(false);
}),
)
.subscribe((supported) => {
if (!supported) {
this.logService.debug("SDK is not supported");
this.sdkService.failedToInitialize("web").catch((e) => this.logService.error(e));
} else {
this.logService.debug("SDK is supported");
}
});
}
}
ngOnInit() { ngOnInit() {
this.i18nService.locale$.pipe(takeUntil(this.destroy$)).subscribe((locale) => { this.i18nService.locale$.pipe(takeUntil(this.destroy$)).subscribe((locale) => {

View File

@@ -1384,7 +1384,6 @@ const safeProviders: SafeProvider[] = [
AccountServiceAbstraction, AccountServiceAbstraction,
KdfConfigService, KdfConfigService,
KeyServiceAbstraction, KeyServiceAbstraction,
ApiServiceAbstraction,
], ],
}), }),
safeProvider({ safeProvider({

View File

@@ -7,11 +7,6 @@ import { BitwardenClient } from "@bitwarden/sdk-internal";
import { UserId } from "../../../types/guid"; import { UserId } from "../../../types/guid";
export abstract class SdkService { export abstract class SdkService {
/**
* Check if the SDK is supported in the current environment.
*/
supported$: Observable<boolean>;
/** /**
* Retrieve the version of the SDK. * Retrieve the version of the SDK.
*/ */
@@ -35,6 +30,4 @@ export abstract class SdkService {
* @param userId * @param userId
*/ */
abstract userClient$(userId: UserId): Observable<BitwardenClient>; abstract userClient$(userId: UserId): Observable<BitwardenClient>;
abstract failedToInitialize(category: string, error?: Error): Promise<void>;
} }

View File

@@ -4,7 +4,6 @@ import { BehaviorSubject, firstValueFrom, of } from "rxjs";
import { KdfConfigService, KeyService, PBKDF2KdfConfig } from "@bitwarden/key-management"; import { KdfConfigService, KeyService, PBKDF2KdfConfig } from "@bitwarden/key-management";
import { BitwardenClient } from "@bitwarden/sdk-internal"; import { BitwardenClient } from "@bitwarden/sdk-internal";
import { ApiService } from "../../../abstractions/api.service";
import { AccountInfo, AccountService } from "../../../auth/abstractions/account.service"; import { AccountInfo, AccountService } from "../../../auth/abstractions/account.service";
import { UserId } from "../../../types/guid"; import { UserId } from "../../../types/guid";
import { UserKey } from "../../../types/key"; import { UserKey } from "../../../types/key";
@@ -24,7 +23,6 @@ describe("DefaultSdkService", () => {
let accountService!: MockProxy<AccountService>; let accountService!: MockProxy<AccountService>;
let kdfConfigService!: MockProxy<KdfConfigService>; let kdfConfigService!: MockProxy<KdfConfigService>;
let keyService!: MockProxy<KeyService>; let keyService!: MockProxy<KeyService>;
let apiService!: MockProxy<ApiService>;
let service!: DefaultSdkService; let service!: DefaultSdkService;
let mockClient!: MockProxy<BitwardenClient>; let mockClient!: MockProxy<BitwardenClient>;
@@ -36,7 +34,6 @@ describe("DefaultSdkService", () => {
accountService = mock<AccountService>(); accountService = mock<AccountService>();
kdfConfigService = mock<KdfConfigService>(); kdfConfigService = mock<KdfConfigService>();
keyService = mock<KeyService>(); keyService = mock<KeyService>();
apiService = mock<ApiService>();
// Can't use `of(mock<Environment>())` for some reason // Can't use `of(mock<Environment>())` for some reason
environmentService.environment$ = new BehaviorSubject(mock<Environment>()); environmentService.environment$ = new BehaviorSubject(mock<Environment>());
@@ -48,7 +45,6 @@ describe("DefaultSdkService", () => {
accountService, accountService,
kdfConfigService, kdfConfigService,
keyService, keyService,
apiService,
); );
mockClient = mock<BitwardenClient>(); mockClient = mock<BitwardenClient>();

View File

@@ -3,7 +3,6 @@
import { import {
combineLatest, combineLatest,
concatMap, concatMap,
firstValueFrom,
Observable, Observable,
shareReplay, shareReplay,
map, map,
@@ -21,7 +20,6 @@ import {
DeviceType as SdkDeviceType, DeviceType as SdkDeviceType,
} from "@bitwarden/sdk-internal"; } from "@bitwarden/sdk-internal";
import { ApiService } from "../../../abstractions/api.service";
import { EncryptedOrganizationKeyData } from "../../../admin-console/models/data/encrypted-organization-key.data"; import { EncryptedOrganizationKeyData } from "../../../admin-console/models/data/encrypted-organization-key.data";
import { AccountInfo, AccountService } from "../../../auth/abstractions/account.service"; import { AccountInfo, AccountService } from "../../../auth/abstractions/account.service";
import { DeviceType } from "../../../enums/device-type.enum"; import { DeviceType } from "../../../enums/device-type.enum";
@@ -34,43 +32,17 @@ import { SdkService } from "../../abstractions/sdk/sdk.service";
import { compareValues } from "../../misc/compare-values"; import { compareValues } from "../../misc/compare-values";
import { EncryptedString } from "../../models/domain/enc-string"; import { EncryptedString } from "../../models/domain/enc-string";
export class RecoverableSDKError extends Error {
sdk: BitwardenClient;
timeout: number;
constructor(sdk: BitwardenClient, timeout: number) {
super(`SDK took ${timeout}s to initialize`);
this.sdk = sdk;
this.timeout = timeout;
}
}
export class DefaultSdkService implements SdkService { export class DefaultSdkService implements SdkService {
private sdkClientCache = new Map<UserId, Observable<BitwardenClient>>(); private sdkClientCache = new Map<UserId, Observable<BitwardenClient>>();
client$ = this.environmentService.environment$.pipe( client$ = this.environmentService.environment$.pipe(
concatMap(async (env) => { concatMap(async (env) => {
const settings = this.toSettings(env); const settings = this.toSettings(env);
try {
return await this.sdkClientFactory.createSdkClient(settings, LogLevel.Info); return await this.sdkClientFactory.createSdkClient(settings, LogLevel.Info);
} catch (e) {
if (e instanceof RecoverableSDKError) {
await this.failedToInitialize("sdk", e);
return e.sdk;
}
throw e;
}
}), }),
shareReplay({ refCount: true, bufferSize: 1 }), shareReplay({ refCount: true, bufferSize: 1 }),
); );
supported$ = this.client$.pipe(
concatMap(async (client) => {
return client.echo("bitwarden wasm!") === "bitwarden wasm!";
}),
);
version$ = this.client$.pipe( version$ = this.client$.pipe(
map((client) => client.version()), map((client) => client.version()),
catchError(() => "Unsupported"), catchError(() => "Unsupported"),
@@ -83,7 +55,6 @@ export class DefaultSdkService implements SdkService {
private accountService: AccountService, private accountService: AccountService,
private kdfConfigService: KdfConfigService, private kdfConfigService: KdfConfigService,
private keyService: KeyService, private keyService: KeyService,
private apiService: ApiService, // Yes we shouldn't import ApiService, but it's temporary
private userAgent: string = null, private userAgent: string = null,
) {} ) {}
@@ -155,31 +126,6 @@ export class DefaultSdkService implements SdkService {
return client$; return client$;
} }
async failedToInitialize(category: string, error?: Error): Promise<void> {
// Only log on cloud instances
if (
this.platformUtilsService.isDev() ||
!(await firstValueFrom(this.environmentService.environment$)).isCloud
) {
return;
}
return this.apiService.send(
"POST",
"/wasm-debug",
{
category: category,
error: error?.message,
},
false,
false,
null,
(headers) => {
headers.append("SDK-Version", "1.0.0");
},
);
}
private async initializeClient( private async initializeClient(
client: BitwardenClient, client: BitwardenClient,
account: AccountInfo, account: AccountInfo,