Skip to content

Commit a6229dc

Browse files
committed
Implement remote SSH feature
1 parent 8831c9d commit a6229dc

File tree

74 files changed

+2988
-54
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+2988
-54
lines changed
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Package Native Dependencies
2+
3+
on: workflow_dispatch
4+
5+
jobs:
6+
build:
7+
runs-on: ${{ matrix.os }}
8+
strategy:
9+
matrix:
10+
os: ['ubuntu-latest', 'windows-latest', 'macos-latest']
11+
steps:
12+
- name: Checkout
13+
uses: actions/checkout@v3
14+
15+
- name: Use Node.js 16.14.0
16+
uses: actions/setup-node@v3
17+
with:
18+
node-version: '16.14.0'
19+
registry-url: 'https://registry.npmjs.org'
20+
21+
- name: Use Python 3.x
22+
uses: actions/setup-python@v4
23+
with:
24+
python-version: '3.x'
25+
26+
- name: Install and Build
27+
shell: bash
28+
run: |
29+
yarn --skip-integrity-check --network-timeout 100000
30+
env:
31+
NODE_OPTIONS: --max_old_space_size=4096
32+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # https://github.com/microsoft/vscode-ripgrep/issues/9
33+
34+
- name: Build Browser App
35+
shell: bash
36+
run: |
37+
yarn browser build
38+
env:
39+
NODE_OPTIONS: --max_old_space_size=4096
40+
41+
- name: Zip Native Dependencies
42+
shell: bash
43+
run: yarn zip:native:dependencies
44+
45+
- name: Upload Artifacts
46+
uses: actions/upload-artifact@v3
47+
with:
48+
name: native-dependencies
49+
path: ./scripts/native-dependencies-*.zip

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,4 @@ dependency-check-summary.txt*
3636
.tours
3737
/performance-result.json
3838
*.vsix
39+
/scripts/native-dependencies-*

examples/browser/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"@theia/preview": "1.38.0",
4545
"@theia/process": "1.38.0",
4646
"@theia/property-view": "1.38.0",
47+
"@theia/remote": "1.38.0",
4748
"@theia/scm": "1.38.0",
4849
"@theia/scm-extra": "1.38.0",
4950
"@theia/search-in-workspace": "1.38.0",

examples/browser/tsconfig.json

+3
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@
9595
{
9696
"path": "../../packages/property-view"
9797
},
98+
{
99+
"path": "../../packages/remote"
100+
},
98101
{
99102
"path": "../../packages/scm"
100103
},

examples/electron/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"@theia/preview": "1.38.0",
4646
"@theia/process": "1.38.0",
4747
"@theia/property-view": "1.38.0",
48+
"@theia/remote": "1.38.0",
4849
"@theia/scm": "1.38.0",
4950
"@theia/scm-extra": "1.38.0",
5051
"@theia/search-in-workspace": "1.38.0",

examples/electron/tsconfig.json

+3
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@
9898
{
9999
"path": "../../packages/property-view"
100100
},
101+
{
102+
"path": "../../packages/remote"
103+
},
101104
{
102105
"path": "../../packages/scm"
103106
},

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"@typescript-eslint/eslint-plugin-tslint": "^4.8.1",
2323
"@typescript-eslint/parser": "^4.8.1",
2424
"@vscode/vsce": "^2.15.0",
25+
"archiver": "^5.3.1",
2526
"chai": "4.3.4",
2627
"chai-spies": "1.0.0",
2728
"chai-string": "^1.4.0",
@@ -90,7 +91,8 @@
9091
"watch:compile": "concurrently --kill-others -n cleanup,tsc -c magenta,red \"ts-clean dev-packages/* packages/* -w\" \"tsc -b -w --preserveWatchOutput\"",
9192
"performance:startup": "yarn -s performance:startup:browser && yarn -s performance:startup:electron",
9293
"performance:startup:browser": "concurrently --success first -k -r \"cd scripts/performance && node browser-performance.js --name 'Browser Frontend Startup' --folder browser --runs 10\" \"yarn -s --cwd examples/browser start\"",
93-
"performance:startup:electron": "yarn -s electron rebuild && cd scripts/performance && node electron-performance.js --name 'Electron Frontend Startup' --folder electron --runs 10"
94+
"performance:startup:electron": "yarn -s electron rebuild && cd scripts/performance && node electron-performance.js --name 'Electron Frontend Startup' --folder electron --runs 10",
95+
"zip:native:dependencies": "node ./scripts/zip-native-dependencies.js"
9496
},
9597
"workspaces": [
9698
"dev-packages/*",

packages/core/package.json

+5
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"@types/dompurify": "^2.2.2",
2424
"@types/express": "^4.16.0",
2525
"@types/fs-extra": "^4.0.2",
26+
"@types/glob": "^8.1.0",
2627
"@types/lodash.debounce": "4.0.3",
2728
"@types/lodash.throttle": "^4.1.3",
2829
"@types/markdown-it": "^12.2.3",
@@ -46,6 +47,7 @@
4647
"font-awesome": "^4.7.0",
4748
"fs-extra": "^4.0.2",
4849
"fuzzy": "^0.1.3",
50+
"glob": "^8.1.0",
4951
"http-proxy-agent": "^5.0.0",
5052
"https-proxy-agent": "^5.0.0",
5153
"iconv-lite": "^0.6.0",
@@ -165,6 +167,9 @@
165167
{
166168
"backend": "lib/node/request/backend-request-module",
167169
"backendElectron": "lib/electron-node/request/electron-backend-request-module"
170+
},
171+
{
172+
"backend": "lib/node/remote/backend-remote-module"
168173
}
169174
],
170175
"keywords": [

packages/core/src/browser/common-frontend-contribution.ts

+18
Original file line numberDiff line numberDiff line change
@@ -2202,6 +2202,24 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
22022202
hcLight: Color.lighten('statusBar.offlineBackground', 0.6)
22032203
}, description: 'Background of active statusbar item in case the theia server is offline.'
22042204
},
2205+
{
2206+
id: 'statusBarItem.remoteBackground',
2207+
defaults: {
2208+
dark: 'activityBarBadge.background',
2209+
light: 'activityBarBadge.background',
2210+
hcDark: 'activityBarBadge.background',
2211+
hcLight: 'activityBarBadge.background'
2212+
}, description: 'Background color for the remote indicator on the status bar.'
2213+
},
2214+
{
2215+
id: 'statusBarItem.remoteForeground',
2216+
defaults: {
2217+
dark: 'activityBarBadge.foreground',
2218+
light: 'activityBarBadge.foreground',
2219+
hcDark: 'activityBarBadge.foreground',
2220+
hcLight: 'activityBarBadge.foreground'
2221+
}, description: 'Foreground color for the remote indicator on the status bar.'
2222+
},
22052223
// Buttons
22062224
{
22072225
id: 'secondaryButton.foreground',

packages/core/src/browser/cookies.ts

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// *****************************************************************************
2+
// Copyright (C) 2023 TypeFox and others.
3+
//
4+
// This program and the accompanying materials are made available under the
5+
// terms of the Eclipse Public License v. 2.0 which is available at
6+
// http://www.eclipse.org/legal/epl-2.0.
7+
//
8+
// This Source Code may also be made available under the following Secondary
9+
// Licenses when the conditions for such availability set forth in the Eclipse
10+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
11+
// with the GNU Classpath Exception which is available at
12+
// https://www.gnu.org/software/classpath/license.html.
13+
//
14+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15+
// *****************************************************************************
16+
17+
import { injectable } from 'inversify';
18+
19+
@injectable()
20+
export class CookieService {
21+
22+
set(name: string, value: string): void {
23+
document.cookie = `${name}=${value}`;
24+
}
25+
26+
remove(name: string): void {
27+
document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:01 GMT`;
28+
}
29+
30+
}

packages/core/src/browser/frontend-application-module.ts

+7
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ import { MarkdownRenderer, MarkdownRendererFactory, MarkdownRendererImpl } from
136136
import { StylingParticipant, StylingService } from './styling-service';
137137
import { bindCommonStylingParticipants } from './common-styling-participants';
138138
import { HoverService } from './hover-service';
139+
import { CookieService } from './cookies';
140+
import { NullRemoteService, RemoteService } from './remote-service';
139141

140142
export { bindResourceProvider, bindMessageService, bindPreferenceService };
141143

@@ -441,5 +443,10 @@ export const frontendApplicationModule = new ContainerModule((bind, _unbind, _is
441443
bindContributionProvider(bind, StylingParticipant);
442444
bind(FrontendApplicationContribution).toService(StylingService);
443445

446+
bind(CookieService).toSelf().inSingletonScope();
447+
448+
bind(NullRemoteService).toSelf().inSingletonScope();
449+
bind(RemoteService).toService(NullRemoteService);
450+
444451
bind(SecondaryWindowHandler).toSelf().inSingletonScope();
445452
});

packages/core/src/browser/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,5 @@ export * from './tooltip-service';
4444
export * from './decoration-style';
4545
export * from './styling-service';
4646
export * from './hover-service';
47+
export * from './cookies';
48+
export * from './remote-service';

packages/core/src/browser/messaging/ws-connection-provider.ts

+23-15
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
1515
// *****************************************************************************
1616

17-
import { injectable, interfaces, decorate, unmanaged } from 'inversify';
17+
import { injectable, interfaces, decorate, unmanaged, postConstruct } from 'inversify';
1818
import { JsonRpcProxyFactory, JsonRpcProxy, Emitter, Event, Channel } from '../../common';
1919
import { Endpoint } from '../endpoint';
2020
import { AbstractConnectionProvider } from '../../common/messaging/abstract-connection-provider';
@@ -48,23 +48,15 @@ export class WebSocketConnectionProvider extends AbstractConnectionProvider<WebS
4848
return container.get(WebSocketConnectionProvider).createProxy<T>(path, arg);
4949
}
5050

51-
protected readonly socket: Socket;
51+
protected socket: Socket;
5252

5353
constructor() {
5454
super();
55-
const url = this.createWebSocketUrl(WebSocketChannel.wsPath);
56-
this.socket = this.createWebSocket(url);
57-
this.socket.on('connect', () => {
58-
this.initializeMultiplexer();
59-
if (this.reconnectChannelOpeners.length > 0) {
60-
this.reconnectChannelOpeners.forEach(opener => opener());
61-
this.reconnectChannelOpeners = [];
62-
}
63-
this.socket.on('disconnect', () => this.fireSocketDidClose());
64-
this.socket.on('message', () => this.onIncomingMessageActivityEmitter.fire(undefined));
65-
this.fireSocketDidOpen();
66-
});
67-
this.socket.connect();
55+
}
56+
57+
@postConstruct()
58+
protected init(): void {
59+
this.connect();
6860
}
6961

7062
protected createMainChannel(): Channel {
@@ -111,6 +103,22 @@ export class WebSocketConnectionProvider extends AbstractConnectionProvider<WebS
111103
return new Endpoint({ path }).getRestUrl().toString();
112104
}
113105

106+
protected connect(path: string = WebSocketChannel.wsPath): void {
107+
const url = this.createWebSocketUrl(path);
108+
this.socket = this.createWebSocket(url);
109+
this.socket.on('connect', () => {
110+
this.initializeMultiplexer();
111+
if (this.reconnectChannelOpeners.length > 0) {
112+
this.reconnectChannelOpeners.forEach(opener => opener());
113+
this.reconnectChannelOpeners = [];
114+
}
115+
this.socket.on('disconnect', () => this.fireSocketDidClose());
116+
this.socket.on('message', () => this.onIncomingMessageActivityEmitter.fire(undefined));
117+
this.fireSocketDidOpen();
118+
});
119+
this.socket.connect();
120+
}
121+
114122
/**
115123
* Creates a web socket for the given url
116124
*/

packages/core/src/browser/preloader.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,6 @@ export async function preload(): Promise<void> {
7070
await Promise.allSettled([
7171
loadTranslations(),
7272
loadBackendOS(),
73-
initBackground(),
73+
initBackground()
7474
]);
7575
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// *****************************************************************************
2+
// Copyright (C) 2023 TypeFox and others.
3+
//
4+
// This program and the accompanying materials are made available under the
5+
// terms of the Eclipse Public License v. 2.0 which is available at
6+
// http://www.eclipse.org/legal/epl-2.0.
7+
//
8+
// This Source Code may also be made available under the following Secondary
9+
// Licenses when the conditions for such availability set forth in the Eclipse
10+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
11+
// with the GNU Classpath Exception which is available at
12+
// https://www.gnu.org/software/classpath/license.html.
13+
//
14+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15+
// *****************************************************************************
16+
17+
import { injectable } from 'inversify';
18+
19+
export const RemoteService = Symbol('RemoteService');
20+
21+
export interface RemoteService {
22+
isConnected(): boolean;
23+
}
24+
25+
@injectable()
26+
export class NullRemoteService implements RemoteService {
27+
isConnected(): boolean {
28+
return false;
29+
}
30+
}

packages/core/src/browser/status-bar/status-bar.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ export class StatusBarImpl extends ReactWidget implements StatusBar {
151151
} else {
152152
attrs['aria-label'] = [entry.text, entry.tooltip].join(', ');
153153
}
154+
if (entry.backgroundColor) {
155+
attrs.className += ' has-background';
156+
}
154157

155158
attrs.style = {
156159
color: entry.color || this.color,
@@ -178,8 +181,9 @@ export class StatusBarImpl extends ReactWidget implements StatusBar {
178181
children.push(<span key={key}>{val}</span>);
179182
}
180183
});
181-
const elementInnerDiv = <React.Fragment>{children}</React.Fragment>;
182-
return React.createElement('div', { key: entry.id, ...this.createAttributes(entry) }, elementInnerDiv);
184+
return <div key={entry.id} {...this.createAttributes(entry)}>
185+
{children}
186+
</div>;
183187
}
184188

185189
}

packages/core/src/browser/style/status-bar.css

+12-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ body.theia-no-open-workspace #theia-statusBar {
3030
background: var(--theia-statusBar-noFolderBackground);
3131
color: var(--theia-statusBar-noFolderForeground);
3232
border-top: var(--theia-border-width) solid
33-
var(--theia-statusBar-noFolderBorder);
33+
var(--theia-statusBar-noFolderBorder);
3434
}
3535

3636
#theia-statusBar .area {
@@ -41,7 +41,6 @@ body.theia-no-open-workspace #theia-statusBar {
4141

4242
#theia-statusBar .area.left {
4343
justify-content: flex-start;
44-
padding-left: calc(var(--theia-ui-padding) * 2);
4544
}
4645

4746
#theia-statusBar .area.right {
@@ -56,8 +55,14 @@ body.theia-no-open-workspace #theia-statusBar {
5655
font-size: var(--theia-statusBar-font-size);
5756
}
5857

59-
#theia-statusBar .area .element > * {
60-
margin-left: calc(var(--theia-ui-padding) / 2);
58+
#theia-statusBar .area.left .element.has-background {
59+
margin-left: 0px;
60+
margin-right: 3px;
61+
padding-left: 7px;
62+
padding-right: 7px;
63+
}
64+
#theia-statusBar .area .element>* {
65+
margin-left: calc(var(--theia-ui-padding)/2);
6166
}
6267

6368
#theia-statusBar .area .element .codicon {
@@ -77,6 +82,9 @@ body.theia-no-open-workspace #theia-statusBar {
7782
color: var(--theia-statusBar-offlineForeground) !important;
7883
}
7984

85+
#theia-statusBar .area.left .element:first-child:not(.has-background) {
86+
margin-left: calc(var(--theia-ui-padding) * 3);
87+
}
8088
#theia-statusBar .area.left .element {
8189
margin-right: var(--theia-ui-padding);
8290
}

packages/core/src/common/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,4 @@ export * from './telemetry';
4747
export * from './types';
4848
export { default as URI } from './uri';
4949
export * from './view-column';
50+
export * from './version';

packages/core/src/common/quick-pick-service.ts

+1
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ export interface QuickPickOptions<T extends QuickPickItemOrSeparator> {
271271
onDidTriggerItemButton?: (ItemButtonEvent: QuickPickItemButtonContext<T>) => void
272272
}
273273

274+
export const quickInputServicePath = '/services/quickInput';
274275
export const QuickInputService = Symbol('QuickInputService');
275276
export interface QuickInputService {
276277
readonly backButton: QuickInputButton;

0 commit comments

Comments
 (0)