From cf0fb9a6c2e6b9e04598950cca7ca8bc31c56b5a Mon Sep 17 00:00:00 2001 From: Jonah Iden Date: Thu, 28 Nov 2024 10:38:16 +0100 Subject: [PATCH] Remote: still use settings and configuration from the local user dir Signed-off-by: Jonah Iden --- packages/remote/package.json | 1 + .../local-backend-services.ts | 31 +++++++++ .../remote-frontend-module.ts | 20 ++++++ .../remote-user-storage-provider.ts | 63 +++++++++++++++++++ packages/remote/tsconfig.json | 3 + .../src/browser/user-storage-contribution.ts | 13 +++- 6 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 packages/remote/src/electron-browser/local-backend-services.ts create mode 100644 packages/remote/src/electron-browser/remote-user-storage-provider.ts diff --git a/packages/remote/package.json b/packages/remote/package.json index a73ecfc6bd16a..cc47c3d283f14 100644 --- a/packages/remote/package.json +++ b/packages/remote/package.json @@ -5,6 +5,7 @@ "dependencies": { "@theia/core": "1.55.0", "@theia/filesystem": "1.55.0", + "@theia/userstorage": "1.55.0", "archiver": "^5.3.1", "decompress": "^4.2.1", "decompress-tar": "^4.0.0", diff --git a/packages/remote/src/electron-browser/local-backend-services.ts b/packages/remote/src/electron-browser/local-backend-services.ts new file mode 100644 index 0000000000000..61697304e2fcf --- /dev/null +++ b/packages/remote/src/electron-browser/local-backend-services.ts @@ -0,0 +1,31 @@ +// ***************************************************************************** +// Copyright (C) 2024 TypeFox and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0. +// +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License v. 2.0 are satisfied: GNU General Public License, version 2 +// with the GNU Classpath Exception which is available at +// https://www.gnu.org/software/classpath/license.html. +// +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 +// ***************************************************************************** + +import { RpcProxy } from '@theia/core'; +import { inject, injectable } from '@theia/core/shared/inversify'; +import { RemoteFileSystemProvider, RemoteFileSystemServer } from '@theia/filesystem/lib/common/remote-file-system-provider'; + +export const LocalEnvVariablesServer = Symbol('LocalEnviromentVariableServer'); +export const LocalRemoteFileSytemServer = Symbol('LocalRemoteFileSytemServer'); + +/** + * provide file access to local files while connected to a remote workspace or dev container. + */ +@injectable() +export class LocalRemoteFileSystemProvider extends RemoteFileSystemProvider { + @inject(LocalRemoteFileSytemServer) + protected override readonly server: RpcProxy; +} diff --git a/packages/remote/src/electron-browser/remote-frontend-module.ts b/packages/remote/src/electron-browser/remote-frontend-module.ts index 599c9ef3906d3..537cb498f1bd1 100644 --- a/packages/remote/src/electron-browser/remote-frontend-module.ts +++ b/packages/remote/src/electron-browser/remote-frontend-module.ts @@ -32,6 +32,11 @@ import { PortForwardingService } from './port-forwarding/port-forwarding-service import { RemotePortForwardingProvider, RemoteRemotePortForwardingProviderPath } from '../electron-common/remote-port-forwarding-provider'; import { ServiceConnectionProvider } from '@theia/core/lib/browser/messaging/service-connection-provider'; import '../../src/electron-browser/style/port-forwarding-widget.css'; +import { UserStorageContribution } from '@theia/userstorage/lib/browser/user-storage-contribution'; +import { RemoteUserStorageContribution } from './remote-user-storage-provider'; +import { remoteFileSystemPath, RemoteFileSystemProxyFactory, RemoteFileSystemServer } from '@theia/filesystem/lib/common/remote-file-system-provider'; +import { LocalEnvVariablesServer, LocalRemoteFileSystemProvider, LocalRemoteFileSytemServer } from './local-backend-services'; +import { envVariablesPath, EnvVariablesServer } from '@theia/core/lib/common/env-variables'; export default new ContainerModule((bind, _, __, rebind) => { bind(RemoteFrontendContribution).toSelf().inSingletonScope(); @@ -65,4 +70,19 @@ export default new ContainerModule((bind, _, __, rebind) => { bind(RemotePortForwardingProvider).toDynamicValue(ctx => ServiceConnectionProvider.createLocalProxy(ctx.container, RemoteRemotePortForwardingProviderPath)).inSingletonScope(); + bind(LocalRemoteFileSytemServer).toDynamicValue(ctx => + isRemoteConnection() ? + ServiceConnectionProvider.createLocalProxy(ctx.container, remoteFileSystemPath, new RemoteFileSystemProxyFactory()) : + ctx.container.get(RemoteFileSystemServer)); + bind(LocalEnvVariablesServer).toDynamicValue(ctx => + isRemoteConnection() ? + ServiceConnectionProvider.createLocalProxy(ctx.container, envVariablesPath) : + ctx.container.get(EnvVariablesServer)); + bind(LocalRemoteFileSystemProvider).toSelf().inSingletonScope(); + rebind(UserStorageContribution).to(RemoteUserStorageContribution); + }); + +function isRemoteConnection(): boolean { + return !!new URLSearchParams(window.location.search).get('localPort'); +} diff --git a/packages/remote/src/electron-browser/remote-user-storage-provider.ts b/packages/remote/src/electron-browser/remote-user-storage-provider.ts new file mode 100644 index 0000000000000..35d42245ffe76 --- /dev/null +++ b/packages/remote/src/electron-browser/remote-user-storage-provider.ts @@ -0,0 +1,63 @@ +// ***************************************************************************** +// Copyright (C) 2024 TypeFox and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0. +// +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License v. 2.0 are satisfied: GNU General Public License, version 2 +// with the GNU Classpath Exception which is available at +// https://www.gnu.org/software/classpath/license.html. +// +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 +// ***************************************************************************** + +import { injectable, inject, postConstruct } from '@theia/core/shared/inversify'; +import { FileService } from '@theia/filesystem/lib/browser/file-service'; +import { FileSystemProvider } from '@theia/filesystem/lib/common/files'; +import { UserStorageContribution } from '@theia/userstorage/lib/browser/user-storage-contribution'; +import { RemoteStatusService } from '../electron-common/remote-status-service'; +import { LocalEnvVariablesServer, LocalRemoteFileSystemProvider } from './local-backend-services'; +import { Deferred } from '@theia/core/lib/common/promise-util'; +import { URI } from '@theia/core'; +import { EnvVariablesServer } from '@theia/core/lib/common/env-variables'; + +/** + * This overide is to have remote connections still use settings, keymaps, etc. from the local machine. + */ +@injectable() +export class RemoteUserStorageContribution extends UserStorageContribution { + @inject(RemoteStatusService) + protected readonly remoteStatusService: RemoteStatusService; + + @inject(LocalRemoteFileSystemProvider) + protected readonly localRemoteFileSystemProvider: LocalRemoteFileSystemProvider; + + @inject(LocalEnvVariablesServer) + protected readonly localEnvironments: EnvVariablesServer; + + isRemoteConnection: Deferred = new Deferred(); + + @postConstruct() + protected init(): void { + const port = new URLSearchParams(location.search).get('port'); + if (port) { + this.remoteStatusService.getStatus(Number(port)).then(status => this.isRemoteConnection.resolve(status.alive)); + } + } + + protected override async getDelegate(service: FileService): Promise { + return await this.isRemoteConnection.promise ? + this.localRemoteFileSystemProvider + : service.activateProvider('file'); + } + + protected override async getCongigDirUri(): Promise { + return await this.isRemoteConnection.promise ? + new URI(await this.localEnvironments.getConfigDirUri()) + : super.getCongigDirUri(); + } + +} diff --git a/packages/remote/tsconfig.json b/packages/remote/tsconfig.json index 583ad6411ef85..6ab2143003036 100644 --- a/packages/remote/tsconfig.json +++ b/packages/remote/tsconfig.json @@ -14,6 +14,9 @@ }, { "path": "../filesystem" + }, + { + "path": "../userstorage" } ] } diff --git a/packages/userstorage/src/browser/user-storage-contribution.ts b/packages/userstorage/src/browser/user-storage-contribution.ts index b988885d5681d..cc7f6971324fb 100644 --- a/packages/userstorage/src/browser/user-storage-contribution.ts +++ b/packages/userstorage/src/browser/user-storage-contribution.ts @@ -22,6 +22,7 @@ import { FileSystemProvider } from '@theia/filesystem/lib/common/files'; import { FileService, FileServiceContribution } from '@theia/filesystem/lib/browser/file-service'; import { DelegatingFileSystemProvider } from '@theia/filesystem/lib/common/delegating-file-system-provider'; import { UserStorageUri } from './user-storage-uri'; +import { MaybePromise } from '@theia/core'; @injectable() export class UserStorageContribution implements FileServiceContribution { @@ -40,9 +41,17 @@ export class UserStorageContribution implements FileServiceContribution { }); } + protected getDelegate(service: FileService): MaybePromise { + return service.activateProvider('file'); + } + + protected async getCongigDirUri(): Promise { + return new URI(await this.environments.getConfigDirUri()); + } + protected async createProvider(service: FileService): Promise { - const delegate = await service.activateProvider('file'); - const configDirUri = new URI(await this.environments.getConfigDirUri()); + const delegate = await this.getDelegate(service); + const configDirUri = await this.getCongigDirUri(); return new DelegatingFileSystemProvider(delegate, { uriConverter: { to: resource => {