UNPKG

@sussudio/platform

Version:

Internal APIs for VS Code's service injection the base services.

301 lines (300 loc) 11 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? (desc = Object.getOwnPropertyDescriptor(target, key)) : desc, d; if (typeof Reflect === 'object' && typeof Reflect.decorate === 'function') r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if ((d = decorators[i])) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); }; }; import { URI } from '@sussudio/base/common/uri.mjs'; import { once } from '@sussudio/base/common/functional.mjs'; import { Emitter } from '@sussudio/base/common/event.mjs'; import { Disposable } from '@sussudio/base/common/lifecycle.mjs'; import { IEnvironmentService } from '../../environment/common/environment.mjs'; import { IFileService } from '../../files/common/files.mjs'; import { createDecorator } from '../../instantiation/common/instantiation.mjs'; import { ILifecycleMainService } from '../../lifecycle/electron-main/lifecycleMainService.mjs'; import { ILogService } from '../../log/common/log.mjs'; import { AbstractStorageService, isProfileUsingDefaultStorage } from '../common/storage.mjs'; import { ApplicationStorageMain, ProfileStorageMain, InMemoryStorageMain, WorkspaceStorageMain, } from './storageMain.mjs'; import { IUserDataProfilesService } from '../../userDataProfile/common/userDataProfile.mjs'; import { IUserDataProfilesMainService } from '../../userDataProfile/electron-main/userDataProfile.mjs'; import { IUriIdentityService } from '../../uriIdentity/common/uriIdentity.mjs'; //#region Storage Main Service (intent: make application, profile and workspace storage accessible to windows from main process) export const IStorageMainService = createDecorator('storageMainService'); let StorageMainService = class StorageMainService extends Disposable { logService; environmentService; userDataProfilesService; lifecycleMainService; fileService; uriIdentityService; shutdownReason = undefined; _onDidChangeProfileStorage = this._register(new Emitter()); onDidChangeProfileStorage = this._onDidChangeProfileStorage.event; constructor( logService, environmentService, userDataProfilesService, lifecycleMainService, fileService, uriIdentityService, ) { super(); this.logService = logService; this.environmentService = environmentService; this.userDataProfilesService = userDataProfilesService; this.lifecycleMainService = lifecycleMainService; this.fileService = fileService; this.uriIdentityService = uriIdentityService; this.registerListeners(); } getStorageOptions() { return { useInMemoryStorage: !!this.environmentService.extensionTestsLocationURI, // no storage during extension tests! }; } registerListeners() { // Application Storage: Warmup when any window opens (async () => { await this.lifecycleMainService.when(3 /* LifecycleMainPhase.AfterWindowOpen */); this.applicationStorage.init(); })(); this._register( this.lifecycleMainService.onWillLoadWindow((e) => { // Profile Storage: Warmup when related window with profile loads if (e.window.profile) { this.profileStorage(e.window.profile).init(); } // Workspace Storage: Warmup when related window with workspace loads if (e.workspace) { this.workspaceStorage(e.workspace).init(); } }), ); // All Storage: Close when shutting down this._register( this.lifecycleMainService.onWillShutdown((e) => { this.logService.trace('storageMainService#onWillShutdown()'); // Remember shutdown reason this.shutdownReason = e.reason; // Application Storage e.join(this.applicationStorage.close()); // Profile Storage(s) for (const [, profileStorage] of this.mapProfileToStorage) { e.join(profileStorage.close()); } // Workspace Storage(s) for (const [, workspaceStorage] of this.mapWorkspaceToStorage) { e.join(workspaceStorage.close()); } }), ); // Prepare storage location as needed this._register( this.userDataProfilesService.onWillCreateProfile((e) => { e.join( (async () => { if (!(await this.fileService.exists(e.profile.globalStorageHome))) { await this.fileService.createFolder(e.profile.globalStorageHome); } })(), ); }), ); // Close the storage of the profile that is being removed this._register( this.userDataProfilesService.onWillRemoveProfile((e) => { const storage = this.mapProfileToStorage.get(e.profile.id); if (storage) { e.join(storage.close()); } }), ); } //#region Application Storage applicationStorage = this.createApplicationStorage(); createApplicationStorage() { this.logService.trace(`StorageMainService: creating application storage`); const applicationStorage = new ApplicationStorageMain( this.getStorageOptions(), this.userDataProfilesService, this.logService, this.fileService, ); once(applicationStorage.onDidCloseStorage)(() => { this.logService.trace(`StorageMainService: closed application storage`); }); return applicationStorage; } //#endregion //#region Profile Storage mapProfileToStorage = new Map(); profileStorage(profile) { if (isProfileUsingDefaultStorage(profile)) { return this.applicationStorage; // for profiles using default storage, use application storage } let profileStorage = this.mapProfileToStorage.get(profile.id); if (!profileStorage) { this.logService.trace(`StorageMainService: creating profile storage (${profile.name})`); profileStorage = this.createProfileStorage(profile); this.mapProfileToStorage.set(profile.id, profileStorage); const listener = this._register( profileStorage.onDidChangeStorage((e) => this._onDidChangeProfileStorage.fire({ ...e, storage: profileStorage, profile, }), ), ); once(profileStorage.onDidCloseStorage)(() => { this.logService.trace(`StorageMainService: closed profile storage (${profile.name})`); this.mapProfileToStorage.delete(profile.id); listener.dispose(); }); } return profileStorage; } createProfileStorage(profile) { if (this.shutdownReason === 2 /* ShutdownReason.KILL */) { // Workaround for native crashes that we see when // SQLite DBs are being created even after shutdown // https://github.com/microsoft/vscode/issues/143186 return new InMemoryStorageMain(this.logService, this.fileService); } return new ProfileStorageMain(profile, this.getStorageOptions(), this.logService, this.fileService); } //#endregion //#region Workspace Storage mapWorkspaceToStorage = new Map(); workspaceStorage(workspace) { let workspaceStorage = this.mapWorkspaceToStorage.get(workspace.id); if (!workspaceStorage) { this.logService.trace(`StorageMainService: creating workspace storage (${workspace.id})`); workspaceStorage = this.createWorkspaceStorage(workspace); this.mapWorkspaceToStorage.set(workspace.id, workspaceStorage); once(workspaceStorage.onDidCloseStorage)(() => { this.logService.trace(`StorageMainService: closed workspace storage (${workspace.id})`); this.mapWorkspaceToStorage.delete(workspace.id); }); } return workspaceStorage; } createWorkspaceStorage(workspace) { if (this.shutdownReason === 2 /* ShutdownReason.KILL */) { // Workaround for native crashes that we see when // SQLite DBs are being created even after shutdown // https://github.com/microsoft/vscode/issues/143186 return new InMemoryStorageMain(this.logService, this.fileService); } return new WorkspaceStorageMain( workspace, this.getStorageOptions(), this.logService, this.environmentService, this.fileService, ); } //#endregion isUsed(path) { const pathUri = URI.file(path); for (const storage of [ this.applicationStorage, ...this.mapProfileToStorage.values(), ...this.mapWorkspaceToStorage.values(), ]) { if (!storage.path) { continue; } if (this.uriIdentityService.extUri.isEqualOrParent(URI.file(storage.path), pathUri)) { return true; } } return false; } }; StorageMainService = __decorate( [ __param(0, ILogService), __param(1, IEnvironmentService), __param(2, IUserDataProfilesMainService), __param(3, ILifecycleMainService), __param(4, IFileService), __param(5, IUriIdentityService), ], StorageMainService, ); export { StorageMainService }; //#endregion //#region Application Main Storage Service (intent: use application storage from main process) export const IApplicationStorageMainService = createDecorator('applicationStorageMainService'); let ApplicationStorageMainService = class ApplicationStorageMainService extends AbstractStorageService { userDataProfilesService; storageMainService; whenReady = this.storageMainService.applicationStorage.whenInit; constructor(userDataProfilesService, storageMainService) { super(); this.userDataProfilesService = userDataProfilesService; this.storageMainService = storageMainService; } doInitialize() { // application storage is being initialized as part // of the first window opening, so we do not trigger // it here but can join it return this.storageMainService.applicationStorage.whenInit; } getStorage(scope) { if (scope === -1 /* StorageScope.APPLICATION */) { return this.storageMainService.applicationStorage.storage; } return undefined; // any other scope is unsupported from main process } getLogDetails(scope) { if (scope === -1 /* StorageScope.APPLICATION */) { return this.userDataProfilesService.defaultProfile.globalStorageHome.fsPath; } return undefined; // any other scope is unsupported from main process } shouldFlushWhenIdle() { return false; // not needed here, will be triggered from any window that is opened } switch() { throw new Error('Migrating storage is unsupported from main process'); } switchToProfile() { throw new Error('Switching storage profile is unsupported from main process'); } switchToWorkspace() { throw new Error('Switching storage workspace is unsupported from main process'); } hasScope() { throw new Error('Main process is never profile or workspace scoped'); } }; ApplicationStorageMainService = __decorate( [__param(0, IUserDataProfilesService), __param(1, IStorageMainService)], ApplicationStorageMainService, ); export { ApplicationStorageMainService };