1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-12 14:23:32 +00:00

[PM-6797] Prevent account switching race condition on desktop & enable worker decryption (#9312)

* Prevent account switching race condition on desktop

This enables us to allow background thread / multithread bulk decryption on desktop.

* Disable account switcher component during switching
This commit is contained in:
Bernd Schoolmann
2024-07-11 14:11:51 +02:00
committed by GitHub
parent f03dabb6d6
commit e977dacdcf
7 changed files with 22 additions and 26 deletions

View File

@@ -210,7 +210,6 @@ import { AutofillService as AutofillServiceAbstraction } from "../autofill/servi
import AutofillService from "../autofill/services/autofill.service"; import AutofillService from "../autofill/services/autofill.service";
import { SafariApp } from "../browser/safariApp"; import { SafariApp } from "../browser/safariApp";
import { BrowserApi } from "../platform/browser/browser-api"; import { BrowserApi } from "../platform/browser/browser-api";
import { flagEnabled } from "../platform/flags";
import { UpdateBadge } from "../platform/listeners/update-badge"; import { UpdateBadge } from "../platform/listeners/update-badge";
/* eslint-disable no-restricted-imports */ /* eslint-disable no-restricted-imports */
import { ChromeMessageSender } from "../platform/messaging/chrome-message.sender"; import { ChromeMessageSender } from "../platform/messaging/chrome-message.sender";
@@ -484,8 +483,7 @@ export default class MainBackground {
storageServiceProvider, storageServiceProvider,
); );
this.encryptService = this.encryptService = BrowserApi.isManifestVersion(2)
flagEnabled("multithreadDecryption") && BrowserApi.isManifestVersion(2)
? new MultithreadEncryptServiceImplementation( ? new MultithreadEncryptServiceImplementation(
this.cryptoFunctionService, this.cryptoFunctionService,
this.logService, this.logService,

View File

@@ -1,7 +1,6 @@
{ {
"devFlags": {}, "devFlags": {},
"flags": { "flags": {
"multithreadDecryption": false,
"enableCipherKeyEncryption": true "enableCipherKeyEncryption": true
} }
} }

View File

@@ -422,12 +422,13 @@ export class AppComponent implements OnInit, OnDestroy {
} else { } else {
this.messagingService.send("unlocked"); this.messagingService.send("unlocked");
this.loading = true; this.loading = true;
await this.syncService.fullSync(true); await this.syncService.fullSync(false);
this.loading = false; this.loading = false;
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. // 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 // eslint-disable-next-line @typescript-eslint/no-floating-promises
this.router.navigate(["vault"]); this.router.navigate(["vault"]);
} }
this.messagingService.send("finishSwitchAccount");
break; break;
} }
case "systemSuspended": case "systemSuspended":

View File

@@ -7,6 +7,7 @@
cdkOverlayOrigin cdkOverlayOrigin
#trigger="cdkOverlayOrigin" #trigger="cdkOverlayOrigin"
[hidden]="!view.showSwitcher" [hidden]="!view.showSwitcher"
[disabled]="disabled"
aria-haspopup="dialog" aria-haspopup="dialog"
> >
<ng-container *ngIf="view.activeAccount; else noActiveAccount"> <ng-container *ngIf="view.activeAccount; else noActiveAccount">

View File

@@ -12,6 +12,7 @@ import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authenticatio
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { CommandDefinition, MessageListener } from "@bitwarden/common/platform/messaging";
import { UserId } from "@bitwarden/common/types/guid"; import { UserId } from "@bitwarden/common/types/guid";
type ActiveAccount = { type ActiveAccount = {
@@ -75,12 +76,14 @@ export class AccountSwitcherComponent {
showSwitcher$: Observable<boolean>; showSwitcher$: Observable<boolean>;
numberOfAccounts$: Observable<number>; numberOfAccounts$: Observable<number>;
disabled = false;
constructor( constructor(
private stateService: StateService, private stateService: StateService,
private authService: AuthService, private authService: AuthService,
private avatarService: AvatarService, private avatarService: AvatarService,
private messagingService: MessagingService, private messagingService: MessagingService,
private messageListener: MessageListener,
private router: Router, private router: Router,
private environmentService: EnvironmentService, private environmentService: EnvironmentService,
private loginEmailService: LoginEmailServiceAbstraction, private loginEmailService: LoginEmailServiceAbstraction,
@@ -159,7 +162,13 @@ export class AccountSwitcherComponent {
async switch(userId: string) { async switch(userId: string) {
this.close(); this.close();
this.messagingService.send("switchAccount", { userId: userId }); this.disabled = true;
const accountSwitchFinishedPromise = firstValueFrom(
this.messageListener.messages$(new CommandDefinition("finishSwitchAccount")),
);
this.messagingService.send("switchAccount", { userId });
await accountSwitchFinishedPromise;
this.disabled = false;
} }
async addAccount() { async addAccount() {

View File

@@ -154,7 +154,7 @@ import { StateFactory } from "@bitwarden/common/platform/factories/state-factory
import { Message, MessageListener, MessageSender } from "@bitwarden/common/platform/messaging"; import { Message, MessageListener, MessageSender } from "@bitwarden/common/platform/messaging";
// eslint-disable-next-line no-restricted-imports -- Used for dependency injection // eslint-disable-next-line no-restricted-imports -- Used for dependency injection
import { SubjectMessageSender } from "@bitwarden/common/platform/messaging/internal"; import { SubjectMessageSender } from "@bitwarden/common/platform/messaging/internal";
import { devFlagEnabled, flagEnabled } from "@bitwarden/common/platform/misc/flags"; import { devFlagEnabled } from "@bitwarden/common/platform/misc/flags";
import { Account } from "@bitwarden/common/platform/models/domain/account"; import { Account } from "@bitwarden/common/platform/models/domain/account";
import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state"; import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state";
import { AppIdService } from "@bitwarden/common/platform/services/app-id.service"; import { AppIdService } from "@bitwarden/common/platform/services/app-id.service";
@@ -162,7 +162,6 @@ import { ConfigApiService } from "@bitwarden/common/platform/services/config/con
import { DefaultConfigService } from "@bitwarden/common/platform/services/config/default-config.service"; import { DefaultConfigService } from "@bitwarden/common/platform/services/config/default-config.service";
import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service"; import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service";
import { CryptoService } from "@bitwarden/common/platform/services/crypto.service"; import { CryptoService } from "@bitwarden/common/platform/services/crypto.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 { MultithreadEncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/multithread-encrypt.service.implementation";
import { DefaultBroadcasterService } from "@bitwarden/common/platform/services/default-broadcaster.service"; import { DefaultBroadcasterService } from "@bitwarden/common/platform/services/default-broadcaster.service";
import { DefaultEnvironmentService } from "@bitwarden/common/platform/services/default-environment.service"; import { DefaultEnvironmentService } from "@bitwarden/common/platform/services/default-environment.service";
@@ -822,7 +821,7 @@ const safeProviders: SafeProvider[] = [
}), }),
safeProvider({ safeProvider({
provide: EncryptService, provide: EncryptService,
useFactory: encryptServiceFactory, useClass: MultithreadEncryptServiceImplementation,
deps: [CryptoFunctionServiceAbstraction, LogService, LOG_MAC_FAILURES], deps: [CryptoFunctionServiceAbstraction, LogService, LOG_MAC_FAILURES],
}), }),
safeProvider({ safeProvider({
@@ -1242,16 +1241,6 @@ const safeProviders: SafeProvider[] = [
}), }),
]; ];
function encryptServiceFactory(
cryptoFunctionservice: CryptoFunctionServiceAbstraction,
logService: LogService,
logMacFailures: boolean,
): EncryptService {
return flagEnabled("multithreadDecryption")
? new MultithreadEncryptServiceImplementation(cryptoFunctionservice, logService, logMacFailures)
: new EncryptServiceImplementation(cryptoFunctionservice, logService, logMacFailures);
}
@NgModule({ @NgModule({
declarations: [], declarations: [],
// Do not register your dependency here! Add it to the typesafeProviders array using the helper function // Do not register your dependency here! Add it to the typesafeProviders array using the helper function

View File

@@ -1,7 +1,6 @@
// required to avoid linting errors when there are no flags // required to avoid linting errors when there are no flags
// eslint-disable-next-line @typescript-eslint/ban-types // eslint-disable-next-line @typescript-eslint/ban-types
export type SharedFlags = { export type SharedFlags = {
multithreadDecryption: boolean;
showPasswordless?: boolean; showPasswordless?: boolean;
enableCipherKeyEncryption?: boolean; enableCipherKeyEncryption?: boolean;
}; };