sussudio
Version:
An unofficial VS Code Internal API
246 lines (245 loc) • 12.1 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* 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 "../../../base/common/uri.mjs";
import { once } from "../../../base/common/functional.mjs";
import { Emitter } from "../../../base/common/event.mjs";
import { Disposable } from "../../../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 };