Skip to content

Commit

Permalink
Remote: still use settings and configuration from the local user dir (#…
Browse files Browse the repository at this point in the history
…14548)

* Remote: still use settings and configuration from the local user dir

---------

Signed-off-by: Jonah Iden <[email protected]>
  • Loading branch information
jonah-iden authored Dec 3, 2024
1 parent 15e9e26 commit 66c1b9d
Show file tree
Hide file tree
Showing 11 changed files with 145 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

- [Previous Changelogs](https://github.com/eclipse-theia/theia/tree/master/doc/changelogs/)

<a name="breaking_changes_1.57.0">[Breaking Changes:](#breaking_changes_1.57.0)</a>

- [remote] use local settings and configuration while connected to remote (rebinds UserStorageProvider) [#14548]https://github.com/eclipse-theia/theia/pull/14548/

## 1.56.0 - 11/28/2024

- [ai] added support for users to specify custom request settings, model, and optionally provider-specific [#14535](https://github.com/eclipse-theia/theia/pull/14535)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ export function getLocalPort(): string | undefined {
return params.get('localPort') ?? undefined;
}

export function getCurrentPort(): string | undefined {
const params = new URLSearchParams(location.search);
return params.get('port') ?? undefined;
}

@injectable()
export class ElectronLocalWebSocketConnectionSource extends WebSocketConnectionSource {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { FrontendApplicationContribution } from '@theia/core/lib/browser';
import type { ContainerInspectInfo } from 'dockerode';
import { RemoteContainerConnectionProvider } from '../electron-common/remote-container-connection-provider';
import { PortForwardingService } from '@theia/remote/lib/electron-browser/port-forwarding/port-forwarding-service';
import { getCurrentPort } from '@theia/core/lib/electron-browser/messaging/electron-local-ws-connection-source';

@injectable()
export class ContainerInfoContribution implements FrontendApplicationContribution {
Expand All @@ -32,7 +33,7 @@ export class ContainerInfoContribution implements FrontendApplicationContributio
containerInfo: ContainerInspectInfo | undefined;

async onStart(): Promise<void> {
this.containerInfo = await this.connectionProvider.getCurrentContainerInfo(parseInt(new URLSearchParams(location.search).get('port') ?? '0'));
this.containerInfo = await this.connectionProvider.getCurrentContainerInfo(parseInt(getCurrentPort() ?? '0'));

this.portForwardingService.forwardedPorts = Object.entries(this.containerInfo?.NetworkSettings.Ports ?? {}).flatMap(([_, ports]) => (
ports.map(port => ({
Expand Down
1 change: 1 addition & 0 deletions packages/remote/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"dependencies": {
"@theia/core": "1.56.0",
"@theia/filesystem": "1.56.0",
"@theia/userstorage": "1.56.0",
"archiver": "^5.3.1",
"decompress": "^4.2.1",
"decompress-tar": "^4.0.0",
Expand Down
31 changes: 31 additions & 0 deletions packages/remote/src/electron-browser/local-backend-services.ts
Original file line number Diff line number Diff line change
@@ -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<RemoteFileSystemServer>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import { Emitter } from '@theia/core';
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
import { RemotePortForwardingProvider } from '../../electron-common/remote-port-forwarding-provider';
import { getCurrentPort } from '@theia/core/lib/electron-browser/messaging/electron-local-ws-connection-source';

export interface ForwardedPort {
localPort?: number;
Expand Down Expand Up @@ -50,7 +51,7 @@ export class PortForwardingService {
}

updatePort(port: ForwardedPort, newAdress: string): void {
const connectionPort = new URLSearchParams(location.search).get('port');
const connectionPort = getCurrentPort();
if (!connectionPort) {
// if there is no open remote connection we can't forward a port
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { RemoteStatus, RemoteStatusService } from '../electron-common/remote-sta
import { RemoteRegistry, RemoteRegistryContribution } from './remote-registry-contribution';
import { RemoteService } from './remote-service';
import { WindowService } from '@theia/core/lib/browser/window/window-service';
import { getLocalPort, getCurrentPort } from '@theia/core/lib/electron-browser/messaging/electron-local-ws-connection-source';

export namespace RemoteCommands {
export const REMOTE_SELECT: Command = {
Expand Down Expand Up @@ -59,7 +60,7 @@ export class RemoteFrontendContribution implements CommandContribution, Frontend
protected remoteRegistry = new RemoteRegistry();

async configure(): Promise<void> {
const port = new URLSearchParams(location.search).get('port');
const port = getCurrentPort();
if (port) {
const status = await this.remoteStatusService.getStatus(Number(port));
await this.setStatusBar(status);
Expand Down Expand Up @@ -106,9 +107,9 @@ export class RemoteFrontendContribution implements CommandContribution, Frontend
}

protected async disconnectRemote(): Promise<void> {
const searchParams = new URLSearchParams(location.search);
const localPort = searchParams.get('localPort');
const localPort = getLocalPort();
if (localPort) {
const searchParams = new URLSearchParams(location.search);
const currentPort = searchParams.get('port');
this.remoteStatusService.connectionClosed(parseInt(currentPort ?? '0'));
this.windowService.reload({ search: { port: localPort } });
Expand Down
19 changes: 18 additions & 1 deletion packages/remote/src/electron-browser/remote-frontend-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import { bindContributionProvider, CommandContribution } from '@theia/core';
import { ContainerModule } from '@theia/core/shared/inversify';
import { bindViewContribution, FrontendApplicationContribution, WidgetFactory } from '@theia/core/lib/browser';
import { bindViewContribution, FrontendApplicationContribution, isRemote, WidgetFactory } from '@theia/core/lib/browser';
import { RemoteSSHContribution } from './remote-ssh-contribution';
import { RemoteSSHConnectionProvider, RemoteSSHConnectionProviderPath } from '../electron-common/remote-ssh-connection-provider';
import { RemoteFrontendContribution } from './remote-frontend-contribution';
Expand All @@ -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();
Expand Down Expand Up @@ -65,4 +70,16 @@ export default new ContainerModule((bind, _, __, rebind) => {
bind(RemotePortForwardingProvider).toDynamicValue(ctx =>
ServiceConnectionProvider.createLocalProxy<RemotePortForwardingProvider>(ctx.container, RemoteRemotePortForwardingProviderPath)).inSingletonScope();

bind(LocalRemoteFileSytemServer).toDynamicValue(ctx =>
isRemote ?
ServiceConnectionProvider.createLocalProxy(ctx.container, remoteFileSystemPath, new RemoteFileSystemProxyFactory()) :
ctx.container.get(RemoteFileSystemServer));
bind(LocalEnvVariablesServer).toDynamicValue(ctx =>
isRemote ?
ServiceConnectionProvider.createLocalProxy<EnvVariablesServer>(ctx.container, envVariablesPath) :
ctx.container.get(EnvVariablesServer));
bind(LocalRemoteFileSystemProvider).toSelf().inSingletonScope();
rebind(UserStorageContribution).to(RemoteUserStorageContribution);

});

Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// *****************************************************************************
// 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';
import { getCurrentPort } from '@theia/core/lib/electron-browser/messaging/electron-local-ws-connection-source';

/**
* 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<boolean> = new Deferred();

@postConstruct()
protected init(): void {
const port = getCurrentPort();
if (port) {
this.remoteStatusService.getStatus(Number(port)).then(status => this.isRemoteConnection.resolve(status.alive));
}
}

protected override async getDelegate(service: FileService): Promise<FileSystemProvider> {
return await this.isRemoteConnection.promise ?
this.localRemoteFileSystemProvider
: service.activateProvider('file');
}

protected override async getCongigDirUri(): Promise<URI> {
return await this.isRemoteConnection.promise ?
new URI(await this.localEnvironments.getConfigDirUri())
: super.getCongigDirUri();
}

}
3 changes: 3 additions & 0 deletions packages/remote/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
},
{
"path": "../filesystem"
},
{
"path": "../userstorage"
}
]
}
13 changes: 11 additions & 2 deletions packages/userstorage/src/browser/user-storage-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -40,9 +41,17 @@ export class UserStorageContribution implements FileServiceContribution {
});
}

protected getDelegate(service: FileService): MaybePromise<FileSystemProvider> {
return service.activateProvider('file');
}

protected async getCongigDirUri(): Promise<URI> {
return new URI(await this.environments.getConfigDirUri());
}

protected async createProvider(service: FileService): Promise<FileSystemProvider> {
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 => {
Expand Down

0 comments on commit 66c1b9d

Please sign in to comment.