mirror of
https://github.com/bitwarden/browser
synced 2025-12-12 22:33:35 +00:00
[PM-7978] Create ForegroundSyncService For Delegating fullSync Calls (#9192)
* Create ForegroundSyncService For Delegating `fullSync` calls to the background * Relax `isExternalMessage` to Allow For Typed Payload * Null Coalesce The `startListening` Method * Filter To Only External Messages
This commit is contained in:
@@ -230,6 +230,8 @@ import { BrowserPlatformUtilsService } from "../platform/services/platform-utils
|
||||
import { BackgroundMemoryStorageService } from "../platform/storage/background-memory-storage.service";
|
||||
import { BrowserStorageServiceProvider } from "../platform/storage/browser-storage-service.provider";
|
||||
import { ForegroundMemoryStorageService } from "../platform/storage/foreground-memory-storage.service";
|
||||
import { ForegroundSyncService } from "../platform/sync/foreground-sync.service";
|
||||
import { SyncServiceListener } from "../platform/sync/sync-service.listener";
|
||||
import { fromChromeRuntimeMessaging } from "../platform/utils/from-chrome-runtime-messaging";
|
||||
import VaultTimeoutService from "../services/vault-timeout/vault-timeout.service";
|
||||
import FilelessImporterBackground from "../tools/background/fileless-importer.background";
|
||||
@@ -339,6 +341,7 @@ export default class MainBackground {
|
||||
scriptInjectorService: BrowserScriptInjectorService;
|
||||
kdfConfigService: kdfConfigServiceAbstraction;
|
||||
offscreenDocumentService: OffscreenDocumentService;
|
||||
syncServiceListener: SyncServiceListener;
|
||||
|
||||
onUpdatedRan: boolean;
|
||||
onReplacedRan: boolean;
|
||||
@@ -792,32 +795,52 @@ export default class MainBackground {
|
||||
|
||||
this.providerService = new ProviderService(this.stateProvider);
|
||||
|
||||
this.syncService = new SyncService(
|
||||
this.masterPasswordService,
|
||||
this.accountService,
|
||||
this.apiService,
|
||||
this.domainSettingsService,
|
||||
this.folderService,
|
||||
this.cipherService,
|
||||
this.cryptoService,
|
||||
this.collectionService,
|
||||
this.messagingService,
|
||||
this.policyService,
|
||||
this.sendService,
|
||||
this.logService,
|
||||
this.keyConnectorService,
|
||||
this.stateService,
|
||||
this.providerService,
|
||||
this.folderApiService,
|
||||
this.organizationService,
|
||||
this.sendApiService,
|
||||
this.userDecryptionOptionsService,
|
||||
this.avatarService,
|
||||
logoutCallback,
|
||||
this.billingAccountProfileStateService,
|
||||
this.tokenService,
|
||||
this.authService,
|
||||
);
|
||||
if (this.popupOnlyContext) {
|
||||
this.syncService = new ForegroundSyncService(
|
||||
this.stateService,
|
||||
this.folderService,
|
||||
this.folderApiService,
|
||||
this.messagingService,
|
||||
this.logService,
|
||||
this.cipherService,
|
||||
this.collectionService,
|
||||
this.apiService,
|
||||
this.accountService,
|
||||
this.authService,
|
||||
this.sendService,
|
||||
this.sendApiService,
|
||||
messageListener,
|
||||
);
|
||||
} else {
|
||||
this.syncService = new SyncService(
|
||||
this.masterPasswordService,
|
||||
this.accountService,
|
||||
this.apiService,
|
||||
this.domainSettingsService,
|
||||
this.folderService,
|
||||
this.cipherService,
|
||||
this.cryptoService,
|
||||
this.collectionService,
|
||||
this.messagingService,
|
||||
this.policyService,
|
||||
this.sendService,
|
||||
this.logService,
|
||||
this.keyConnectorService,
|
||||
this.stateService,
|
||||
this.providerService,
|
||||
this.folderApiService,
|
||||
this.organizationService,
|
||||
this.sendApiService,
|
||||
this.userDecryptionOptionsService,
|
||||
this.avatarService,
|
||||
logoutCallback,
|
||||
this.billingAccountProfileStateService,
|
||||
this.tokenService,
|
||||
this.authService,
|
||||
);
|
||||
|
||||
this.syncServiceListener = new SyncServiceListener(this.syncService, messageListener);
|
||||
}
|
||||
this.eventUploadService = new EventUploadService(
|
||||
this.apiService,
|
||||
this.stateProvider,
|
||||
@@ -1141,6 +1164,7 @@ export default class MainBackground {
|
||||
this.contextMenusBackground?.init();
|
||||
await this.idleBackground.init();
|
||||
this.webRequestBackground?.startListening();
|
||||
this.syncServiceListener?.startListening();
|
||||
|
||||
return new Promise<void>((resolve) => {
|
||||
setTimeout(async () => {
|
||||
|
||||
79
apps/browser/src/platform/sync/foreground-sync.service.ts
Normal file
79
apps/browser/src/platform/sync/foreground-sync.service.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { firstValueFrom, timeout } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import {
|
||||
CommandDefinition,
|
||||
MessageListener,
|
||||
MessageSender,
|
||||
} from "@bitwarden/common/platform/messaging";
|
||||
import { CoreSyncService } from "@bitwarden/common/platform/sync/internal";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { InternalSendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction";
|
||||
import { InternalFolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
|
||||
const SYNC_COMPLETED = new CommandDefinition<{ successfully: boolean }>("syncCompleted");
|
||||
export const DO_FULL_SYNC = new CommandDefinition<{
|
||||
forceSync: boolean;
|
||||
allowThrowOnError: boolean;
|
||||
}>("doFullSync");
|
||||
|
||||
export class ForegroundSyncService extends CoreSyncService {
|
||||
constructor(
|
||||
stateService: StateService,
|
||||
folderService: InternalFolderService,
|
||||
folderApiService: FolderApiServiceAbstraction,
|
||||
messageSender: MessageSender,
|
||||
logService: LogService,
|
||||
cipherService: CipherService,
|
||||
collectionService: CollectionService,
|
||||
apiService: ApiService,
|
||||
accountService: AccountService,
|
||||
authService: AuthService,
|
||||
sendService: InternalSendService,
|
||||
sendApiService: SendApiService,
|
||||
private readonly messageListener: MessageListener,
|
||||
) {
|
||||
super(
|
||||
stateService,
|
||||
folderService,
|
||||
folderApiService,
|
||||
messageSender,
|
||||
logService,
|
||||
cipherService,
|
||||
collectionService,
|
||||
apiService,
|
||||
accountService,
|
||||
authService,
|
||||
sendService,
|
||||
sendApiService,
|
||||
);
|
||||
}
|
||||
|
||||
async fullSync(forceSync: boolean, allowThrowOnError: boolean = false): Promise<boolean> {
|
||||
this.syncInProgress = true;
|
||||
try {
|
||||
const syncCompletedPromise = firstValueFrom(
|
||||
this.messageListener.messages$(SYNC_COMPLETED).pipe(
|
||||
timeout({
|
||||
first: 10_000,
|
||||
with: () => {
|
||||
throw new Error("Timeout while doing a fullSync call.");
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
this.messageSender.send(DO_FULL_SYNC, { forceSync, allowThrowOnError });
|
||||
const result = await syncCompletedPromise;
|
||||
return result.successfully;
|
||||
} finally {
|
||||
this.syncInProgress = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
apps/browser/src/platform/sync/sync-service.listener.ts
Normal file
25
apps/browser/src/platform/sync/sync-service.listener.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { Subscription, concatMap, filter } from "rxjs";
|
||||
|
||||
import { MessageListener, isExternalMessage } from "@bitwarden/common/platform/messaging";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
|
||||
import { DO_FULL_SYNC } from "./foreground-sync.service";
|
||||
|
||||
export class SyncServiceListener {
|
||||
constructor(
|
||||
private readonly syncService: SyncService,
|
||||
private readonly messageListener: MessageListener,
|
||||
) {}
|
||||
|
||||
startListening(): Subscription {
|
||||
return this.messageListener
|
||||
.messages$(DO_FULL_SYNC)
|
||||
.pipe(
|
||||
filter((message) => isExternalMessage(message)),
|
||||
concatMap(async ({ forceSync, allowThrowOnError }) => {
|
||||
await this.syncService.fullSync(forceSync, allowThrowOnError);
|
||||
}),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user