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:
@@ -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,
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"devFlags": {},
|
"devFlags": {},
|
||||||
"flags": {
|
"flags": {
|
||||||
"multithreadDecryption": false,
|
|
||||||
"enableCipherKeyEncryption": true
|
"enableCipherKeyEncryption": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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":
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user