Compare commits

...

13 Commits

Author SHA1 Message Date
Asher
d0215eca88 Tweak bug report template
These checkboxes keep getting checked despite the submitter using an
insecure context or not having tested upstream.  I think two things are
at play here:

1. Folks might be interpreting "cannot reproduce" as "did not
   reproduce" or "did not have time to reproduce".
2. The checkboxes are required to submit the issue so folks might be
   marking them just so they can get their issue submitted; maybe they
   are not even reading the checkboxes and are just seeing the error
   that they need to be marked and blindly marking them because while
   in some cases folks will add "I had to check this but it is not
   true", usually they say nothing.

In any case, hopefully these changes make the checkboxes more accurate,
and then if they are unchecked we can ask them to go reproduce in VS
Code or use a secure context or whatever the case may be.
2023-12-18 13:56:35 -09:00
Dov Benyomin Sohacheski
d6c5a4af9c Add Debian bookworm config to bakefile (#6590) 2023-12-18 21:30:16 +00:00
Olivier Benz
0b84523121 Update Code to 1.85.1 (#6588) 2023-12-18 20:18:44 +00:00
Olivier Benz
45694d38c4 Update Code to 1.85.0 (#6573) 2023-12-15 12:38:01 -09:00
Dov Benyomin Sohacheski
d9fe46a6be Update and organize release image packages, add wget (#6581) 2023-12-15 20:32:14 +00:00
Ammar Bandukwala
6f078a48a6 Improve README callout to coder/coder (#6579) 2023-12-12 14:23:54 -09:00
Dov Benyomin Sohacheski
7649b6e6ca Update base release image to Debian:12 (#6574) 2023-12-12 11:37:17 -09:00
Jeff Miller
9622830518 Disable "Show Local" button, add --disable-file-uploads option and add file operation trace level logs (#6557) 2023-12-07 12:10:22 -09:00
Asher
26a3437849 Use debug instead of trace
Trace outputs stack traces which is entirely unnecessary for these two
log entries and makes the logs noisier than they need to be.
2023-12-06 13:19:36 -09:00
Evan Rush
1fac50d6f6 Fix Helm boolean environment variable (#6563) 2023-12-04 19:32:16 +00:00
Asher
3e8100b70e Release v4.19.1 2023-11-29 12:23:25 -09:00
Asher
0c98611e6b Ensure we only ever set workspace initialized to true
This is just a guard in case there are paths where the workspace is
already marked as initialized but the workspace configuration is not and
we end up actually un-initializing it.
2023-11-27 17:36:26 -09:00
Asher
73cb236535 Add back local storage patch
And fix the workspace bug.  It is caused by an issue with how some
global variables are being used asynchronously and is exacerbated by the
delay reading settings from the remote introduces.

1. The workspace is created and is marked as not initialized.
2. The configuration's change handler is triggered, and now
   initialization is complete.
3. The handler tries to set the global workspace variable to initialized
   but the workspace has not been set yet so we get an undefined error.
4. The workspace global is now set, but it is set to the old value with
   initialized still set to false.
5. Workspace is never marked as initialized until something else
   triggers the on change handler again.

Fixes #3061, and closes #6546.

My guess is this logic changed in one of the VS Code updates,
introducing this async bug but never getting caught probably because for
them the settings are always local thus minimal delay.
2023-11-27 17:25:38 -09:00
30 changed files with 723 additions and 314 deletions

View File

@@ -36,7 +36,7 @@ body:
2. install extension
3. run command
value: |
1.
1.
2.
3.
validations:
@@ -67,19 +67,23 @@ body:
- type: checkboxes
attributes:
label: Does this issue happen in VS Code or GitHub Codespaces?
description: Please try reproducing this issue in VS Code or GitHub Codespaces
description: Please try reproducing this issue in VS Code and GitHub Codespaces. If the bug reproduces in either VS Code or GitHub Codespaces, please submit the issue upstream instead (https://github.com/microsoft/vscode).
options:
- label: I cannot reproduce this in VS Code.
required: true
- label: I cannot reproduce this in GitHub Codespaces.
required: true
- label: I tested this in native VS Code.
required: false
- label: This does not happen in native VS Code.
required: false
- label: I tested this in GitHub Codespaces.
required: false
- label: This does not happen in GitHub Codespaces.
required: false
- type: checkboxes
attributes:
label: Are you accessing code-server over a secure context?
description: code-server relies on service workers (which only work in secure contexts) for many features. Double-check that you are using a secure context like HTTPS or localhost.
options:
- label: I am using a secure context.
required: true
required: false
- type: textarea
attributes:
label: Notes

View File

@@ -22,6 +22,15 @@ Code v99.99.999
## Unreleased
## [4.19.1](https://github.com/coder/code-server/releases/tag/v4.19.1) - 2023-11-29
Code v1.84.2
### Fixed
- Fixed an issue where parts of the editor would not load (like the file
explorer, source control, etc) when using a workspace file.
## [4.19.0](https://github.com/coder/code-server/releases/tag/v4.19.0) - 2023-11-18
Code v1.84.2

View File

@@ -15,9 +15,9 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 3.15.0
version: 3.15.1
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
appVersion: 4.19.0
appVersion: 4.19.1

View File

@@ -6,7 +6,7 @@ replicaCount: 1
image:
repository: codercom/code-server
tag: '4.19.0'
tag: '4.19.1'
pullPolicy: Always
# Specifies one or more secrets to be used when pulling images from a
@@ -71,7 +71,7 @@ extraArgs: []
# Optional additional environment variables
extraVars: []
# - name: DISABLE_TELEMETRY
# value: true
# value: "true"
# - name: DOCKER_HOST
# value: "tcp://localhost:2375"

View File

@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:experimental
ARG BASE=debian:11
ARG BASE=debian:12
FROM scratch AS packages
COPY release-packages/code-server*.deb /tmp/
@@ -10,18 +10,19 @@ RUN apt-get update \
&& apt-get install -y \
curl \
dumb-init \
zsh \
htop \
locales \
man \
nano \
git \
git-lfs \
procps \
openssh-client \
sudo \
vim.tiny \
htop \
locales \
lsb-release \
man-db \
nano \
openssh-client \
procps \
sudo \
vim-tiny \
wget \
zsh \
&& git lfs install \
&& rm -rf /var/lib/apt/lists/*
@@ -34,7 +35,7 @@ RUN adduser --gecos '' --disabled-password coder \
&& echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
RUN ARCH="$(dpkg --print-architecture)" \
&& curl -fsSL "https://github.com/boxboat/fixuid/releases/download/v0.5/fixuid-0.5-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - \
&& curl -fsSL "https://github.com/boxboat/fixuid/releases/download/v0.6.0/fixuid-0.6.0-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - \
&& chown root:root /usr/local/bin/fixuid \
&& chmod 4755 /usr/local/bin/fixuid \
&& mkdir -p /etc/fixuid \

View File

@@ -16,7 +16,7 @@ variable "GITHUB_REGISTRY" {
group "default" {
targets = [
"code-server-debian-11",
"code-server-debian-12",
"code-server-ubuntu-focal",
]
}
@@ -45,12 +45,12 @@ function "gen_tags_for_docker_and_ghcr" {
)
}
target "code-server-debian-11" {
target "code-server-debian-12" {
dockerfile = "ci/release-image/Dockerfile"
tags = concat(
gen_tags_for_docker_and_ghcr(""),
gen_tags_for_docker_and_ghcr("debian"),
gen_tags_for_docker_and_ghcr("bullseye"),
gen_tags_for_docker_and_ghcr("bookworm"),
)
platforms = ["linux/amd64", "linux/arm64"]
}

View File

@@ -127,13 +127,13 @@ while quilt push; do quilt refresh; done
0. You can go through the patch stack with `quilt push` and `quilt pop`.
1. Create a new patch (`quilt new {name}.diff`) or use an existing patch.
2. Add the file(s) you are patching (`quilt add [-P patch] {file}`). A file
1. Add the file(s) you are patching (`quilt add [-P patch] {file}`). A file
**must** be added before you make changes to it.
3. Make your changes. Patches do not need to be independent of each other but
1. Make your changes. Patches do not need to be independent of each other but
each patch must result in a working code-server without any broken in-between
states otherwise they are difficult to test and modify.
4. Add your changes to the patch (`quilt refresh`)
5. Add a comment in the patch about the reason for the patch and how to
1. Add your changes to the patch (`quilt refresh`)
1. Add a comment in the patch about the reason for the patch and how to
reproduce the behavior it fixes or adds. Every patch should have an e2e test
as well.

View File

@@ -73,7 +73,7 @@ details.
Interested in [working at Coder](https://coder.com/careers)? Check out [our open
positions](https://coder.com/careers#openings)!
## For Organizations
## For Teams
Want remote development for your organization or enterprise? Visit [our
website](https://coder.com) to learn more about Coder.
We develop [coder/coder](https://cdr.co/coder-github) to help teams to
adopt remote development.

View File

@@ -22,7 +22,7 @@ The following steps walk you through setting up a VM running Debian using Google
Cloud (though you are welcome to use any machine or VM provider).
If you're [signing up with Google](https://console.cloud.google.com/getting-started) for the first time, you should get a 3-month trial with
$300 of credits.
\$300 of credits.
After you sign up and create a new Google Cloud Provider (GCP) project, create a
new Compute Engine VM instance:

View File

@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/src/vs/base/common/network.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/base/common/network.ts
+++ code-server/lib/vscode/src/vs/base/common/network.ts
@@ -168,7 +168,9 @@ class RemoteAuthoritiesImpl {
@@ -181,7 +181,9 @@ class RemoteAuthoritiesImpl {
return URI.from({
scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,
authority: `${host}:${port}`,
@@ -99,11 +99,11 @@ Index: code-server/lib/vscode/src/vs/platform/remote/browser/browserSocketFactor
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
+++ code-server/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
@@ -280,6 +280,7 @@ export class BrowserSocketFactory implem
@@ -281,6 +281,7 @@ export class BrowserSocketFactory implem
connect({ host, port }: WebSocketRemoteConnection, path: string, query: string, debugLabel: string): Promise<ISocket> {
return new Promise<ISocket>((resolve, reject) => {
const webSocketSchema = (/^https:/.test(window.location.href) ? 'wss' : 'ws');
+ path = (window.location.pathname + "/" + path).replace(/\/\/+/g, "/")
const webSocketSchema = (/^https:/.test(mainWindow.location.href) ? 'wss' : 'ws');
+ path = (mainWindow.location.pathname + "/" + path).replace(/\/\/+/g, "/")
const socket = this._webSocketFactory.create(`${webSocketSchema}://${(/:/.test(host) && !/\[/.test(host)) ? `[${host}]` : host}:${port}${path}?${query}&skipWebSocketFrames=false`, debugLabel);
const errorListener = socket.onError(reject);
socket.onOpen(() => {
@@ -159,16 +159,16 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
};
if (useTestResolver) {
@@ -367,7 +372,7 @@ export class WebClientServer {
@@ -369,7 +374,7 @@ export class WebClientServer {
'default-src \'self\';',
'img-src \'self\' https: data: blob:;',
'media-src \'self\';',
- `script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} 'sha256-fh3TwPMflhsEIpR8g1OYTIMVWhXTLcjQ9kh2tIpmv54=' ${useTestResolver ? '' : `http://${remoteAuthority}`};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
+ `script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} 'sha256-fh3TwPMflhsEIpR8g1OYTIMVWhXTLcjQ9kh2tIpmv54=' ${useTestResolver ? '' : ''};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
- `script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} '${webWorkerExtensionHostIframeScriptSHA}' ${useTestResolver ? '' : `http://${remoteAuthority}`};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
+ `script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} '${webWorkerExtensionHostIframeScriptSHA}' ${useTestResolver ? '' : ''};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
'child-src \'self\';',
`frame-src 'self' https://*.vscode-cdn.net data:;`,
'worker-src \'self\' data: blob:;',
@@ -440,3 +445,70 @@ export class WebClientServer {
@@ -442,3 +447,70 @@ export class WebClientServer {
return void res.end(data);
}
}
@@ -259,9 +259,9 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
this.startListening();
}
- return URI.parse(window.location.href).with({ path: this._callbackRoute, query: queryParams.join('&') });
+ const path = (window.location.pathname + "/" + this._callbackRoute).replace(/\/\/+/g, "/");
+ return URI.parse(window.location.href).with({ path: path, query: queryParams.join('&') });
- return URI.parse(mainWindow.location.href).with({ path: this._callbackRoute, query: queryParams.join('&') });
+ const path = (mainWindow.location.pathname + "/" + this._callbackRoute).replace(/\/\/+/g, "/");
+ return URI.parse(mainWindow.location.href).with({ path: path, query: queryParams.join('&') });
}
private startListening(): void {

View File

@@ -7,7 +7,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
@@ -244,6 +244,10 @@ export class Extension implements IExten
@@ -245,6 +245,10 @@ export class Extension implements IExten
if (this.type === ExtensionType.System && this.productService.quality === 'stable') {
return false;
}

View File

@@ -1,176 +0,0 @@
Add option to disable file downloads via CLI
This patch adds support for a new CLI flag called `--disable-file-downloads`
which allows a user to remove the "Download..." option that shows up when you
right-click files in Code. The default value for this is `false`.
To test this, start code-server with `--disable-file-downloads`, open editor,
right-click on a file (not a folder) and you should **not** see the
"Download..." option.
Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -276,6 +276,11 @@ export interface IWorkbenchConstructionO
*/
readonly configurationDefaults?: Record<string, any>;
+ /**
+ * Whether the "Download..." option is enabled for files.
+ */
+ readonly isEnabledFileDownloads?: boolean
+
//#endregion
//#region Profile options
Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
@@ -34,6 +34,11 @@ export interface IBrowserWorkbenchEnviro
readonly options?: IWorkbenchConstructionOptions;
/**
+ * Enable downloading files via menu actions.
+ */
+ readonly isEnabledFileDownloads?: boolean;
+
+ /**
* Gets whether a resolver extension is expected for the environment.
*/
readonly expectsResolverExtension: boolean;
@@ -110,6 +115,13 @@ export class BrowserWorkbenchEnvironment
@memoize
get cacheHome(): URI { return joinPath(this.userRoamingDataHome, 'caches'); }
+ get isEnabledFileDownloads(): boolean {
+ if (typeof this.options.isEnabledFileDownloads === "undefined") {
+ throw new Error('isEnabledFileDownloads was not provided to the browser');
+ }
+ return this.options.isEnabledFileDownloads;
+ }
+
@memoize
get workspaceStorageHome(): URI { return joinPath(this.userRoamingDataHome, 'workspaceStorage'); }
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
@@ -16,6 +16,7 @@ export const serverOptions: OptionDescri
/* ----- code-server ----- */
'disable-update-check': { type: 'boolean' },
'auth': { type: 'string' },
+ 'disable-file-downloads': { type: 'boolean' },
/* ----- server setup ----- */
@@ -97,6 +98,7 @@ export interface ServerParsedArgs {
/* ----- code-server ----- */
'disable-update-check'?: boolean;
'auth'?: string
+ 'disable-file-downloads'?: boolean;
/* ----- server setup ----- */
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -331,6 +331,7 @@ export class WebClientServer {
const workbenchWebConfiguration = {
remoteAuthority,
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
+ isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
_wrapWebWorkerExtHostInIframe,
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/contextkeys.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
@@ -7,12 +7,12 @@ import { Event } from 'vs/base/common/ev
import { Disposable } from 'vs/base/common/lifecycle';
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from 'vs/platform/contextkey/common/contextkey';
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from 'vs/platform/contextkey/common/contextkeys';
-import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, MaximizedEditorGroupContext, TitleBarVisibleContext, TitleBarStyleContext } from 'vs/workbench/common/contextkeys';
+import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, IsEnabledFileDownloads, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, MaximizedEditorGroupContext, TitleBarVisibleContext, TitleBarStyleContext } from 'vs/workbench/common/contextkeys';
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor';
import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow } from 'vs/base/browser/dom';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
-import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
+import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { WorkbenchState, IWorkspaceContextService, isTemporaryWorkspace } from 'vs/platform/workspace/common/workspace';
import { IWorkbenchLayoutService, Parts, positionToString } from 'vs/workbench/services/layout/browser/layoutService';
@@ -83,7 +83,7 @@ export class WorkbenchContextKeysHandler
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IConfigurationService private readonly configurationService: IConfigurationService,
- @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
+ @IBrowserWorkbenchEnvironmentService private readonly environmentService: IBrowserWorkbenchEnvironmentService,
@IProductService private readonly productService: IProductService,
@IEditorService private readonly editorService: IEditorService,
@IEditorResolverService private readonly editorResolverService: IEditorResolverService,
@@ -219,6 +219,9 @@ export class WorkbenchContextKeysHandler
this.auxiliaryBarVisibleContext = AuxiliaryBarVisibleContext.bindTo(this.contextKeyService);
this.auxiliaryBarVisibleContext.set(this.layoutService.isVisible(Parts.AUXILIARYBAR_PART));
+ // code-server
+ IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true)
+
this.registerListeners();
}
Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
@@ -20,7 +20,7 @@ import { CLOSE_SAVED_EDITORS_COMMAND_ID,
import { AutoSaveAfterShortDelayContext } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
import { WorkbenchListDoubleSelection } from 'vs/platform/list/browser/listService';
import { Schemas } from 'vs/base/common/network';
-import { DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext } from 'vs/workbench/common/contextkeys';
+import { DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, IsEnabledFileDownloads } from 'vs/workbench/common/contextkeys';
import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ThemeIcon } from 'vs/base/common/themables';
@@ -549,13 +549,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
id: DOWNLOAD_COMMAND_ID,
title: DOWNLOAD_LABEL
},
- when: ContextKeyExpr.or(
- // native: for any remote resource
- ContextKeyExpr.and(IsWebContext.toNegated(), ResourceContextKey.Scheme.notEqualsTo(Schemas.file)),
- // web: for any files
- ContextKeyExpr.and(IsWebContext, ExplorerFolderContext.toNegated(), ExplorerRootContext.toNegated()),
- // web: for any folders if file system API support is provided
- ContextKeyExpr.and(IsWebContext, HasWebFileSystemAccess)
+ when: ContextKeyExpr.and(
+ IsEnabledFileDownloads,
+ ContextKeyExpr.or(
+ // native: for any remote resource
+ ContextKeyExpr.and(IsWebContext.toNegated(), ResourceContextKey.Scheme.notEqualsTo(Schemas.file)),
+ // web: for any files
+ ContextKeyExpr.and(IsWebContext, ExplorerFolderContext.toNegated(), ExplorerRootContext.toNegated()),
+ // web: for any folders if file system API support is provided
+ ContextKeyExpr.and(IsWebContext, HasWebFileSystemAccess)
+ )
)
}));
Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
@@ -39,6 +39,8 @@ export const HasWebFileSystemAccess = ne
export const EmbedderIdentifierContext = new RawContextKey<string | undefined>('embedderIdentifier', undefined, localize('embedderIdentifier', 'The identifier of the embedder according to the product service, if one is defined'));
+export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
+
//#endregion

View File

@@ -53,7 +53,7 @@ Index: code-server/lib/vscode/src/vs/base/common/platform.ts
export const LANGUAGE_DEFAULT = 'en';
let _isWindows = false;
@@ -90,17 +88,21 @@ if (typeof navigator === 'object' && !is
@@ -85,17 +83,21 @@ if (typeof navigator === 'object' && !is
_isMobile = _userAgent?.indexOf('Mobi') >= 0;
_isWeb = true;
@@ -98,10 +98,10 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
<!-- Workbench Icon/Manifest/CSS -->
<link rel="icon" href="{{BASE}}/_static/src/browser/media/favicon-dark-support.svg" />
<link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" type="image/x-icon" />
@@ -48,15 +51,26 @@
@@ -48,15 +51,27 @@
// Normalize locale to lowercase because translationServiceUrl is case-sensitive.
// ref: https://github.com/microsoft/vscode/issues/187795
const locale = window.localStorage.getItem('vscode.nls.locale') || navigator.language.toLowerCase();
const locale = localStorage.getItem('vscode.nls.locale') || navigator.language.toLowerCase();
- if (!locale.startsWith('en')) {
- nlsConfig['vs/nls'] = {
- availableLanguages: {
@@ -110,7 +110,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
- translationServiceUrl: '{{WORKBENCH_NLS_BASE_URL}}'
- };
- }
-
+ try {
+ nlsConfig['vs/nls'] = JSON.parse(document.getElementById("vscode-remote-nls-configuration").getAttribute("data-settings"))
+ if (nlsConfig['vs/nls']._resolvedLanguagePackCoreLocation) {
@@ -220,7 +220,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
import { CharCode } from 'vs/base/common/charCode';
import { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
import { IExtensionManifest } from 'vs/platform/extensions/common/extensions';
@@ -343,6 +344,8 @@ export class WebClientServer {
@@ -345,6 +346,8 @@ export class WebClientServer {
callbackRoute: this._callbackRoute
};
@@ -229,7 +229,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
const nlsBaseUrl = this._productService.extensionsGallery?.nlsBaseUrl;
const values: { [key: string]: string } = {
WORKBENCH_WEB_CONFIGURATION: asJSON(workbenchWebConfiguration),
@@ -351,6 +354,7 @@ export class WebClientServer {
@@ -353,6 +356,7 @@ export class WebClientServer {
WORKBENCH_NLS_BASE_URL: vscodeBase + (nlsBaseUrl ? `${nlsBaseUrl}${!nlsBaseUrl.endsWith('/') ? '/' : ''}${this._productService.commit}/${this._productService.version}/` : ''),
BASE: base,
VS_BASE: vscodeBase,
@@ -241,18 +241,18 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
@@ -17,6 +17,7 @@ export const serverOptions: OptionDescri
'disable-update-check': { type: 'boolean' },
@@ -18,6 +18,7 @@ export const serverOptions: OptionDescri
'auth': { type: 'string' },
'disable-file-downloads': { type: 'boolean' },
'disable-file-uploads': { type: 'boolean' },
+ 'locale': { type: 'string' },
/* ----- server setup ----- */
@@ -99,6 +100,7 @@ export interface ServerParsedArgs {
'disable-update-check'?: boolean;
@@ -101,6 +102,7 @@ export interface ServerParsedArgs {
'auth'?: string
'disable-file-downloads'?: boolean;
'disable-file-uploads'?: boolean;
+ 'locale'?: string
/* ----- server setup ----- */
@@ -367,7 +367,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
}
// Prefers to run on UI
@@ -1684,17 +1681,6 @@ export class SetLanguageAction extends E
@@ -1751,17 +1748,6 @@ export class SetLanguageAction extends E
update(): void {
this.enabled = false;
this.class = SetLanguageAction.DisabledClass;
@@ -385,7 +385,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
}
override async run(): Promise<any> {
@@ -1711,7 +1697,6 @@ export class ClearLanguageAction extends
@@ -1778,7 +1764,6 @@ export class ClearLanguageAction extends
private static readonly DisabledClass = `${ClearLanguageAction.EnabledClass} disabled`;
constructor(
@@ -393,7 +393,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
@ILocaleService private readonly localeService: ILocaleService,
) {
super(ClearLanguageAction.ID, ClearLanguageAction.TITLE.value, ClearLanguageAction.DisabledClass, false);
@@ -1721,17 +1706,6 @@ export class ClearLanguageAction extends
@@ -1788,17 +1773,6 @@ export class ClearLanguageAction extends
update(): void {
this.enabled = false;
this.class = ClearLanguageAction.DisabledClass;

View File

@@ -0,0 +1,358 @@
Add option to disable file downloads and uploads via cli
This patch adds support for a new CLI flag called `--disable-file-downloads`
which allows a user to remove the "Download..." option that shows up when you
right-click files in Code. It also disables the "Show Local" button on the dialog
for Save, Save-As and Save Workspace. The default value for this is `false`.
This patch also add support for a new CLI flag called `--disable-file-uploads`
which disables the drag to upload functionality and the "Upload..." option when you
right-click folders in Code. It also disables the "Show Local" button on the dialog
for opening a file. The default value for this is `false`.
This patch also adds trace log statements for when a file is read and written to disk.
To test disabling downloads, start code-server with `--disable-file-downloads`, open editor,
right-click on a file (not a folder) and you should **not** see the
"Download..." option. When saving a file or workspace, the "Show Local" button
should **not** appear on the dialog that comes on screen.
To test disabling uploads, start code-server with `--disable-file-uploads`, open editor,
right-click on a folder (not a file) and you should **not** see the
"Upload..." option. If you drag a file into the file navigator, the file should **not** upload
and appear in the file navigator. When opening a file, the "Show Local" button
should **not** appear on the dialog that comes on screen.
Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -281,6 +281,16 @@ export interface IWorkbenchConstructionO
*/
readonly userDataPath?: string
+ /**
+ * Whether the "Download..." option is enabled for files.
+ */
+ readonly isEnabledFileDownloads?: boolean
+
+ /**
+ * Whether the "Upload..." button is enabled.
+ */
+ readonly isEnabledFileUploads?: boolean
+
//#endregion
//#region Profile options
Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
@@ -34,6 +34,16 @@ export interface IBrowserWorkbenchEnviro
readonly options?: IWorkbenchConstructionOptions;
/**
+ * Enable downloading files via menu actions.
+ */
+ readonly isEnabledFileDownloads?: boolean;
+
+ /**
+ * Enable uploading files via menu actions.
+ */
+ readonly isEnabledFileUploads?: boolean;
+
+ /**
* Gets whether a resolver extension is expected for the environment.
*/
readonly expectsResolverExtension: boolean;
@@ -111,6 +121,20 @@ export class BrowserWorkbenchEnvironment
return this.options.userDataPath;
}
+ get isEnabledFileDownloads(): boolean {
+ if (typeof this.options.isEnabledFileDownloads === "undefined") {
+ throw new Error('isEnabledFileDownloads was not provided to the browser');
+ }
+ return this.options.isEnabledFileDownloads;
+ }
+
+ get isEnabledFileUploads(): boolean {
+ if (typeof this.options.isEnabledFileUploads === "undefined") {
+ throw new Error('isEnabledFileUploads was not provided to the browser');
+ }
+ return this.options.isEnabledFileUploads;
+ }
+
@memoize
get argvResource(): URI { return joinPath(this.userRoamingDataHome, 'argv.json'); }
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
@@ -16,6 +16,8 @@ export const serverOptions: OptionDescri
/* ----- code-server ----- */
'disable-update-check': { type: 'boolean' },
'auth': { type: 'string' },
+ 'disable-file-downloads': { type: 'boolean' },
+ 'disable-file-uploads': { type: 'boolean' },
/* ----- server setup ----- */
@@ -97,6 +99,8 @@ export interface ServerParsedArgs {
/* ----- code-server ----- */
'disable-update-check'?: boolean;
'auth'?: string
+ 'disable-file-downloads'?: boolean;
+ 'disable-file-uploads'?: boolean;
/* ----- server setup ----- */
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -332,6 +332,8 @@ export class WebClientServer {
remoteAuthority,
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
userDataPath: this._environmentService.userDataPath,
+ isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
+ isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'],
_wrapWebWorkerExtHostInIframe,
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/contextkeys.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
@@ -7,12 +7,12 @@ import { Event } from 'vs/base/common/ev
import { Disposable } from 'vs/base/common/lifecycle';
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from 'vs/platform/contextkey/common/contextkey';
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from 'vs/platform/contextkey/common/contextkeys';
-import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, MainEditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, TitleBarVisibleContext, TitleBarStyleContext, MultipleEditorGroupsContext, IsAuxiliaryWindowFocusedContext } from 'vs/workbench/common/contextkeys';
+import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, MainEditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, TitleBarVisibleContext, TitleBarStyleContext, MultipleEditorGroupsContext, IsAuxiliaryWindowFocusedContext, IsEnabledFileDownloads, IsEnabledFileUploads } from 'vs/workbench/common/contextkeys';
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor';
import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow, getActiveWindow } from 'vs/base/browser/dom';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
-import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
+import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { WorkbenchState, IWorkspaceContextService, isTemporaryWorkspace } from 'vs/platform/workspace/common/workspace';
import { IWorkbenchLayoutService, Parts, positionToString } from 'vs/workbench/services/layout/browser/layoutService';
@@ -84,7 +84,7 @@ export class WorkbenchContextKeysHandler
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IConfigurationService private readonly configurationService: IConfigurationService,
- @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
+ @IBrowserWorkbenchEnvironmentService private readonly environmentService: IBrowserWorkbenchEnvironmentService,
@IProductService private readonly productService: IProductService,
@IEditorService private readonly editorService: IEditorService,
@IEditorResolverService private readonly editorResolverService: IEditorResolverService,
@@ -220,6 +220,10 @@ export class WorkbenchContextKeysHandler
this.auxiliaryBarVisibleContext = AuxiliaryBarVisibleContext.bindTo(this.contextKeyService);
this.auxiliaryBarVisibleContext.set(this.layoutService.isVisible(Parts.AUXILIARYBAR_PART));
+ // code-server
+ IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true)
+ IsEnabledFileUploads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileUploads ?? true)
+
this.registerListeners();
}
Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
@@ -20,7 +20,7 @@ import { CLOSE_SAVED_EDITORS_COMMAND_ID,
import { AutoSaveAfterShortDelayContext } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
import { WorkbenchListDoubleSelection } from 'vs/platform/list/browser/listService';
import { Schemas } from 'vs/base/common/network';
-import { DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext } from 'vs/workbench/common/contextkeys';
+import { DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, IsEnabledFileDownloads, IsEnabledFileUploads } from 'vs/workbench/common/contextkeys';
import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ThemeIcon } from 'vs/base/common/themables';
@@ -550,13 +550,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
id: DOWNLOAD_COMMAND_ID,
title: DOWNLOAD_LABEL
},
- when: ContextKeyExpr.or(
- // native: for any remote resource
- ContextKeyExpr.and(IsWebContext.toNegated(), ResourceContextKey.Scheme.notEqualsTo(Schemas.file)),
- // web: for any files
- ContextKeyExpr.and(IsWebContext, ExplorerFolderContext.toNegated(), ExplorerRootContext.toNegated()),
- // web: for any folders if file system API support is provided
- ContextKeyExpr.and(IsWebContext, HasWebFileSystemAccess)
+ when: ContextKeyExpr.and(
+ IsEnabledFileDownloads,
+ ContextKeyExpr.or(
+ // native: for any remote resource
+ ContextKeyExpr.and(IsWebContext.toNegated(), ResourceContextKey.Scheme.notEqualsTo(Schemas.file)),
+ // web: for any files
+ ContextKeyExpr.and(IsWebContext, ExplorerFolderContext.toNegated(), ExplorerRootContext.toNegated()),
+ // web: for any folders if file system API support is provided
+ ContextKeyExpr.and(IsWebContext, HasWebFileSystemAccess)
+ )
)
}));
@@ -568,6 +571,7 @@ MenuRegistry.appendMenuItem(MenuId.Explo
title: UPLOAD_LABEL,
},
when: ContextKeyExpr.and(
+ IsEnabledFileUploads,
// only in web
IsWebContext,
// only on folders
Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
@@ -40,6 +40,9 @@ export const HasWebFileSystemAccess = ne
export const EmbedderIdentifierContext = new RawContextKey<string | undefined>('embedderIdentifier', undefined, localize('embedderIdentifier', 'The identifier of the embedder according to the product service, if one is defined'));
+export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
+export const IsEnabledFileUploads = new RawContextKey<boolean>('isEnabledFileUploads', true, true);
+
//#endregion
Index: code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts
+++ code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts
@@ -18,7 +18,7 @@ import { IModelService } from 'vs/editor
import { ILanguageService } from 'vs/editor/common/languages/language';
import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
import { Schemas } from 'vs/base/common/network';
-import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
+import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IContextKeyService, IContextKey, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { equalsIgnoreCase, format, startsWithIgnoreCase } from 'vs/base/common/strings';
@@ -143,7 +143,7 @@ export class SimpleFileDialog implements
@IFileDialogService private readonly fileDialogService: IFileDialogService,
@IModelService private readonly modelService: IModelService,
@ILanguageService private readonly languageService: ILanguageService,
- @IWorkbenchEnvironmentService protected readonly environmentService: IWorkbenchEnvironmentService,
+ @IBrowserWorkbenchEnvironmentService protected readonly environmentService: IBrowserWorkbenchEnvironmentService,
@IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService,
@IPathService protected readonly pathService: IPathService,
@IKeybindingService private readonly keybindingService: IKeybindingService,
@@ -287,20 +287,22 @@ export class SimpleFileDialog implements
this.filePickBox.autoFocusOnList = false;
this.filePickBox.ignoreFocusOut = true;
this.filePickBox.ok = true;
- if ((this.scheme !== Schemas.file) && this.options && this.options.availableFileSystems && (this.options.availableFileSystems.length > 1) && (this.options.availableFileSystems.indexOf(Schemas.file) > -1)) {
- this.filePickBox.customButton = true;
- this.filePickBox.customLabel = nls.localize('remoteFileDialog.local', 'Show Local');
- let action;
- if (isSave) {
- action = SaveLocalFileCommand;
- } else {
- action = this.allowFileSelection ? (this.allowFolderSelection ? OpenLocalFileFolderCommand : OpenLocalFileCommand) : OpenLocalFolderCommand;
- }
- const keybinding = this.keybindingService.lookupKeybinding(action.ID);
- if (keybinding) {
- const label = keybinding.getLabel();
- if (label) {
- this.filePickBox.customHover = format('{0} ({1})', action.LABEL, label);
+ if ((isSave && this.environmentService.isEnabledFileDownloads) || (!isSave && this.environmentService.isEnabledFileUploads)) {
+ if ((this.scheme !== Schemas.file) && this.options && this.options.availableFileSystems && (this.options.availableFileSystems.length > 1) && (this.options.availableFileSystems.indexOf(Schemas.file) > -1)) {
+ this.filePickBox.customButton = true;
+ this.filePickBox.customLabel = nls.localize('remoteFileDialog.local', 'Show Local');
+ let action;
+ if (isSave) {
+ action = SaveLocalFileCommand;
+ } else {
+ action = this.allowFileSelection ? (this.allowFolderSelection ? OpenLocalFileFolderCommand : OpenLocalFileCommand) : OpenLocalFolderCommand;
+ }
+ const keybinding = this.keybindingService.lookupKeybinding(action.ID);
+ if (keybinding) {
+ const label = keybinding.getLabel();
+ if (label) {
+ this.filePickBox.customHover = format('{0} ({1})', action.LABEL, label);
+ }
}
}
}
Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts
@@ -68,6 +68,7 @@ import { HoverPosition } from 'vs/base/b
import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
import { mainWindow } from 'vs/base/browser/window';
import { IExplorerFileContribution, explorerFileContribRegistry } from 'vs/workbench/contrib/files/browser/explorerFileContrib';
+import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
export class ExplorerDelegate implements IListVirtualDelegate<ExplorerItem> {
@@ -1079,7 +1080,8 @@ export class FileDragAndDrop implements
@IConfigurationService private configurationService: IConfigurationService,
@IInstantiationService private instantiationService: IInstantiationService,
@IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService,
- @IUriIdentityService private readonly uriIdentityService: IUriIdentityService
+ @IUriIdentityService private readonly uriIdentityService: IUriIdentityService,
+ @IBrowserWorkbenchEnvironmentService protected readonly environmentService: IBrowserWorkbenchEnvironmentService
) {
const updateDropEnablement = (e: IConfigurationChangeEvent | undefined) => {
if (!e || e.affectsConfiguration('explorer.enableDragAndDrop')) {
@@ -1283,15 +1285,17 @@ export class FileDragAndDrop implements
// External file DND (Import/Upload file)
if (data instanceof NativeDragAndDropData) {
- // Use local file import when supported
- if (!isWeb || (isTemporaryWorkspace(this.contextService.getWorkspace()) && WebFileSystemAccess.supported(mainWindow))) {
- const fileImport = this.instantiationService.createInstance(ExternalFileImport);
- await fileImport.import(resolvedTarget, originalEvent, mainWindow);
- }
- // Otherwise fallback to browser based file upload
- else {
- const browserUpload = this.instantiationService.createInstance(BrowserFileUpload);
- await browserUpload.upload(target, originalEvent);
+ if (this.environmentService.isEnabledFileUploads) {
+ // Use local file import when supported
+ if (!isWeb || (isTemporaryWorkspace(this.contextService.getWorkspace()) && WebFileSystemAccess.supported(mainWindow))) {
+ const fileImport = this.instantiationService.createInstance(ExternalFileImport);
+ await fileImport.import(resolvedTarget, originalEvent, mainWindow);
+ }
+ // Otherwise fallback to browser based file upload
+ else {
+ const browserUpload = this.instantiationService.createInstance(BrowserFileUpload);
+ await browserUpload.upload(target, originalEvent);
+ }
}
}
Index: code-server/lib/vscode/src/vs/platform/files/node/diskFileSystemProviderServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/files/node/diskFileSystemProviderServer.ts
+++ code-server/lib/vscode/src/vs/platform/files/node/diskFileSystemProviderServer.ts
@@ -92,6 +92,7 @@ export abstract class AbstractDiskFileSy
private async readFile(uriTransformer: IURITransformer, _resource: UriComponents, opts?: IFileAtomicReadOptions): Promise<VSBuffer> {
const resource = this.transformIncoming(uriTransformer, _resource, true);
+ this.logService.trace(`File action: readFile ${resource.path}`);
const buffer = await this.provider.readFile(resource, opts);
return VSBuffer.wrap(buffer);
@@ -110,6 +111,7 @@ export abstract class AbstractDiskFileSy
}
});
+ this.logService.trace(`File action: readFileStream ${resource.path}`);
const fileStream = this.provider.readFileStream(resource, opts, cts.token);
listenStream(fileStream, {
onData: chunk => emitter.fire(VSBuffer.wrap(chunk)),
@@ -130,7 +132,7 @@ export abstract class AbstractDiskFileSy
private writeFile(uriTransformer: IURITransformer, _resource: UriComponents, content: VSBuffer, opts: IFileWriteOptions): Promise<void> {
const resource = this.transformIncoming(uriTransformer, _resource);
-
+ this.logService.trace(`File action: writeFile ${resource.path}`);
return this.provider.writeFile(resource, content.buffer, opts);
}

View File

@@ -10,24 +10,24 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts
@@ -10,7 +10,7 @@ import { IInstantiationService } from 'v
import { IEditorSerializer, IEditorOpenContext } from 'vs/workbench/common/editor';
import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { assertIsDefined } from 'vs/base/common/types';
-import { $, addDisposableListener, append, clearNode, Dimension, reset } from 'vs/base/browser/dom';
+import { $, addDisposableListener, append, clearNode, Dimension, reset, prepend } from 'vs/base/browser/dom';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IProductService } from 'vs/platform/product/common/productService';
import { hiddenEntriesConfigurationKey, IResolvedWalkthrough, IResolvedWalkthroughStep, IWalkthroughsService } from 'vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService';
@@ -59,7 +59,7 @@ import { GettingStartedIndexList } from
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import { $, Dimension, addDisposableListener, append, clearNode, getWindow, reset } from 'vs/base/browser/dom';
+import { $, Dimension, addDisposableListener, append, clearNode, getWindow, reset, prepend } from 'vs/base/browser/dom';
import { renderFormattedText } from 'vs/base/browser/formattedTextRenderer';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { getTelemetryLevel } from 'vs/platform/telemetry/common/telemetryUtils';
import { Button } from 'vs/base/browser/ui/button/button';
@@ -58,7 +58,7 @@ import { IRecentFolder, IRecentWorkspace
import { OpenRecentAction } from 'vs/workbench/browser/actions/windowActions';
import { OpenFileFolderAction, OpenFolderAction, OpenFolderViaWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
-import { WorkbenchStateContext } from 'vs/workbench/common/contextkeys';
+import { IsEnabledCoderGettingStarted, WorkbenchStateContext } from 'vs/workbench/common/contextkeys';
import { OpenFolderAction, OpenFileFolderAction, OpenFolderViaWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions';
import { OpenRecentAction } from 'vs/workbench/browser/actions/windowActions';
import { Toggle } from 'vs/base/browser/ui/toggle/toggle';
import { IEditorOpenContext, IEditorSerializer } from 'vs/workbench/common/editor';
import { IWebviewElement, IWebviewService } from 'vs/workbench/contrib/webview/browser/webview';
import { IFeaturedExtensionsService } from 'vs/workbench/contrib/welcomeGettingStarted/browser/featuredExtensionService';
@@ -793,6 +793,72 @@ export class GettingStartedPage extends
$('p.subtitle.description', {}, localize({ key: 'gettingStarted.editingEvolved', comment: ['Shown as subtitle on the Welcome page.'] }, "Editing evolved"))
);
@@ -135,9 +135,9 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -281,6 +281,11 @@ export interface IWorkbenchConstructionO
@@ -291,6 +291,11 @@ export interface IWorkbenchConstructionO
*/
readonly isEnabledFileDownloads?: boolean
readonly isEnabledFileUploads?: boolean
+ /**
+ * Whether to use Coder's custom Getting Started text.
@@ -151,8 +151,8 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
@@ -39,6 +39,11 @@ export interface IBrowserWorkbenchEnviro
readonly isEnabledFileDownloads?: boolean;
@@ -44,6 +44,11 @@ export interface IBrowserWorkbenchEnviro
readonly isEnabledFileUploads?: boolean;
/**
+ * Enable Coder's custom getting started text.
@@ -163,8 +163,8 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
* Gets whether a resolver extension is expected for the environment.
*/
readonly expectsResolverExtension: boolean;
@@ -122,6 +127,13 @@ export class BrowserWorkbenchEnvironment
return this.options.isEnabledFileDownloads;
@@ -135,6 +140,13 @@ export class BrowserWorkbenchEnvironment
return this.options.isEnabledFileUploads;
}
+ get isEnabledCoderGettingStarted(): boolean {
@@ -175,23 +175,23 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
+ }
+
@memoize
get workspaceStorageHome(): URI { return joinPath(this.userRoamingDataHome, 'workspaceStorage'); }
get argvResource(): URI { return joinPath(this.userRoamingDataHome, 'argv.json'); }
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
@@ -18,6 +18,7 @@ export const serverOptions: OptionDescri
'auth': { type: 'string' },
@@ -19,6 +19,7 @@ export const serverOptions: OptionDescri
'disable-file-downloads': { type: 'boolean' },
'disable-file-uploads': { type: 'boolean' },
'locale': { type: 'string' },
+ 'disable-getting-started-override': { type: 'boolean' },
/* ----- server setup ----- */
@@ -101,6 +102,7 @@ export interface ServerParsedArgs {
'auth'?: string
@@ -103,6 +104,7 @@ export interface ServerParsedArgs {
'disable-file-downloads'?: boolean;
'disable-file-uploads'?: boolean;
'locale'?: string
+ 'disable-getting-started-override'?: boolean,
@@ -201,10 +201,10 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -334,6 +334,7 @@ export class WebClientServer {
remoteAuthority,
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
@@ -336,6 +336,7 @@ export class WebClientServer {
userDataPath: this._environmentService.userDataPath,
isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'],
+ isEnabledCoderGettingStarted: !this._environmentService.args['disable-getting-started-override'],
_wrapWebWorkerExtHostInIframe,
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
@@ -217,15 +217,15 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
import { Disposable } from 'vs/base/common/lifecycle';
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from 'vs/platform/contextkey/common/contextkey';
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from 'vs/platform/contextkey/common/contextkeys';
-import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, IsEnabledFileDownloads, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, MaximizedEditorGroupContext, TitleBarVisibleContext, TitleBarStyleContext } from 'vs/workbench/common/contextkeys';
+import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, IsEnabledFileDownloads, IsEnabledCoderGettingStarted, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, MaximizedEditorGroupContext, TitleBarVisibleContext, TitleBarStyleContext } from 'vs/workbench/common/contextkeys';
-import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, MainEditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, TitleBarVisibleContext, TitleBarStyleContext, MultipleEditorGroupsContext, IsAuxiliaryWindowFocusedContext, IsEnabledFileDownloads, IsEnabledFileUploads } from 'vs/workbench/common/contextkeys';
+import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, MainEditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, TitleBarVisibleContext, TitleBarStyleContext, MultipleEditorGroupsContext, IsAuxiliaryWindowFocusedContext, IsEnabledFileDownloads, IsEnabledFileUploads, IsEnabledCoderGettingStarted, } from 'vs/workbench/common/contextkeys';
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor';
import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow } from 'vs/base/browser/dom';
import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow, getActiveWindow } from 'vs/base/browser/dom';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
@@ -221,6 +221,7 @@ export class WorkbenchContextKeysHandler
@@ -223,6 +223,7 @@ export class WorkbenchContextKeysHandler
// code-server
IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true)
IsEnabledFileUploads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileUploads ?? true)
+ IsEnabledCoderGettingStarted.bindTo(this.contextKeyService).set(this.environmentService.isEnabledCoderGettingStarted ?? true)
this.registerListeners();
@@ -234,10 +234,10 @@ Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
@@ -40,6 +40,7 @@ export const HasWebFileSystemAccess = ne
export const EmbedderIdentifierContext = new RawContextKey<string | undefined>('embedderIdentifier', undefined, localize('embedderIdentifier', 'The identifier of the embedder according to the product service, if one is defined'));
@@ -42,6 +42,7 @@ export const EmbedderIdentifierContext =
export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
export const IsEnabledFileUploads = new RawContextKey<boolean>('isEnabledFileUploads', true, true);
+export const IsEnabledCoderGettingStarted = new RawContextKey<boolean>('isEnabledCoderGettingStarted', true, true);
//#endregion

View File

@@ -176,9 +176,9 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
@@ -65,6 +65,7 @@ import { mixin, safeStringify } from 'vs
@@ -64,6 +64,7 @@ import { IOpenerService } from 'vs/platf
import { mixin, safeStringify } from 'vs/base/common/objects';
import { IndexedDB } from 'vs/base/browser/indexedDB';
import { IWorkspace } from 'vs/workbench/services/host/browser/browserHostService';
import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess';
+import { CodeServerClient } from 'vs/workbench/browser/client';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';

View File

@@ -0,0 +1,94 @@
Make storage local to the remote server
This makes user settings will be stored in the file system instead of in browser
storage. Using browser storage makes sharing or seeding settings between
browsers difficult and remote settings is not a sufficient replacement because
some settings are only allowed to be set on the user level.
Unfortunately this does not affect state which uses a separate method with
IndexedDB and does not appear nearly as easy to redirect to disk.
To test change settings from the UI and on disk while making sure they appear on
the other side.
This patch also resolves a bug where a global value for workspace initialization
is used in a non async-safe way.
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -327,6 +327,7 @@ export class WebClientServer {
const workbenchWebConfiguration = {
remoteAuthority,
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
+ userDataPath: this._environmentService.userDataPath,
_wrapWebWorkerExtHostInIframe,
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -276,6 +276,11 @@ export interface IWorkbenchConstructionO
*/
readonly configurationDefaults?: Record<string, any>;
+ /**
+ * Path to the user data directory.
+ */
+ readonly userDataPath?: string
+
//#endregion
//#region Profile options
Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
@@ -102,7 +102,14 @@ export class BrowserWorkbenchEnvironment
get logFile(): URI { return joinPath(this.windowLogsPath, 'window.log'); }
@memoize
- get userRoamingDataHome(): URI { return URI.file('/User').with({ scheme: Schemas.vscodeUserData }); }
+ get userRoamingDataHome(): URI { return joinPath(URI.file(this.userDataPath).with({ scheme: Schemas.vscodeRemote }), 'User'); }
+
+ get userDataPath(): string {
+ if (!this.options.userDataPath) {
+ throw new Error('userDataPath was not provided to the browser');
+ }
+ return this.options.userDataPath;
+ }
@memoize
get argvResource(): URI { return joinPath(this.userRoamingDataHome, 'argv.json'); }
Index: code-server/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts
@@ -145,8 +145,10 @@ export class WorkspaceService extends Di
this.workspaceConfiguration = this._register(new WorkspaceConfiguration(configurationCache, fileService, uriIdentityService, logService));
this._register(this.workspaceConfiguration.onDidUpdateConfiguration(fromCache => {
this.onWorkspaceConfigurationChanged(fromCache).then(() => {
- this.workspace.initialized = this.workspaceConfiguration.initialized;
- this.checkAndMarkWorkspaceComplete(fromCache);
+ if (this.workspace) { // The workspace may not have been created yet.
+ this.workspace.initialized = this.workspaceConfiguration.initialized;
+ this.checkAndMarkWorkspaceComplete(fromCache);
+ }
});
}));
@@ -552,6 +554,12 @@ export class WorkspaceService extends Di
previousFolders = this.workspace.folders;
this.workspace.update(workspace);
} else {
+ // It is possible for the configuration to become initialized in between
+ // when the workspace was created and this function was called, so check
+ // the configuration again now.
+ if (!workspace.initialized && this.workspaceConfiguration.initialized) {
+ workspace.initialized = true;
+ }
this.workspace = workspace;
}

View File

@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extens
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
@@ -282,10 +282,7 @@ function extensionDescriptionArrayToMap(
@@ -312,10 +312,7 @@ function extensionDescriptionArrayToMap(
}
export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {

View File

@@ -42,7 +42,7 @@ Index: code-server/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityReso
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts
+++ code-server/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts
@@ -33,7 +33,7 @@ export class RemoteAuthorityResolverServ
@@ -34,7 +34,7 @@ export class RemoteAuthorityResolverServ
isWorkbenchOptionsBasedResolution: boolean,
connectionToken: Promise<string> | string | undefined,
resourceUriProvider: ((uri: URI) => URI) | undefined,
@@ -51,16 +51,16 @@ Index: code-server/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityReso
@ILogService private readonly _logService: ILogService,
) {
super();
@@ -84,9 +84,14 @@ export class RemoteAuthorityResolverServ
@@ -85,9 +85,14 @@ export class RemoteAuthorityResolverServ
const connectionToken = await Promise.resolve(this._connectionTokens.get(authority) || this._connectionToken);
performance.mark(`code/didResolveConnectionToken/${authorityPrefix}`);
this._logService.info(`Resolved connection token (${authorityPrefix}) after ${sw.elapsed()} ms`);
+ let options: ResolvedOptions | undefined;
+ if (this.productService.proxyEndpointTemplate) {
+ const proxyUrl = new URL(this.productService.proxyEndpointTemplate, window.location.href);
+ const proxyUrl = new URL(this.productService.proxyEndpointTemplate, mainWindow.location.href);
+ options = { extensionHostEnv: { VSCODE_PROXY_URI: decodeURIComponent(proxyUrl.toString()) }}
+ }
const defaultPort = (/^https:/.test(window.location.href) ? 443 : 80);
const defaultPort = (/^https:/.test(mainWindow.location.href) ? 443 : 80);
const { host, port } = parseAuthorityWithOptionalPort(authority, defaultPort);
- const result: ResolverResult = { authority: { authority, connectTo: new WebSocketRemoteConnection(host, port), connectionToken } };
+ const result: ResolverResult = { authority: { authority, connectTo: new WebSocketRemoteConnection(host, port), connectionToken }, options };
@@ -96,10 +96,10 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
@@ -19,6 +19,7 @@ import { isFolderToOpen, isWorkspaceToOp
import type { IWorkbenchConstructionOptions } from 'vs/workbench/browser/web.api';
@@ -19,6 +19,7 @@ import { ISecretStorageProvider } from '
import { isFolderToOpen, isWorkspaceToOpen } from 'vs/platform/window/common/window';
import type { IWorkbenchConstructionOptions, IWorkspace, IWorkspaceProvider } from 'vs/workbench/browser/web.api';
import { AuthenticationSessionInfo } from 'vs/workbench/services/authentication/browser/authenticationService';
import type { IWorkspace, IWorkspaceProvider } from 'vs/workbench/services/host/browser/browserHostService';
+import { extractLocalHostUriMetaDataForPortMapping, TunnelOptions, TunnelCreationOptions } from 'vs/platform/tunnel/common/tunnel';
import type { IURLCallbackProvider } from 'vs/workbench/services/url/browser/urlService';
import { create } from 'vs/workbench/workbench.web.main';
@@ -148,7 +148,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExpl
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
@@ -76,7 +76,7 @@ export class ForwardedPortsView extends
@@ -81,7 +81,7 @@ export class ForwardedPortsView extends
this.contextKeyListener = undefined;
}

View File

@@ -66,17 +66,3 @@ Index: code-server/lib/vscode/build/lib/tsb/transpiler.ts
loose: false,
minify: {
compress: false,
Index: code-server/lib/vscode/src/vs/base/common/tfIdf.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/base/common/tfIdf.ts
+++ code-server/lib/vscode/src/vs/base/common/tfIdf.ts
@@ -88,8 +88,7 @@ export class TfIdfCalculator {
for (const [word] of input.matchAll(/\b\p{Letter}[\p{Letter}\d]{2,}\b/gu)) {
yield normalize(word);
- // eslint-disable-next-line local/code-no-look-behind-regex
- const camelParts = word.split(/(?<=[a-z])(?=[A-Z])/g);
+ const camelParts = word.split(/(?=[A-Z])/g);
if (camelParts.length > 1) {
for (const part of camelParts) {
// Require at least 3 letters in the parts of a camel case word

View File

@@ -10,9 +10,10 @@ logout.diff
store-socket.diff
proxy-uri.diff
unique-db.diff
local-storage.diff
service-worker.diff
sourcemaps.diff
disable-downloads.diff
external-file-actions.diff
telemetry.diff
display-language.diff
cli-window-open.diff

View File

@@ -13,7 +13,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/storage/browser/storageS
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/storage/browser/storageService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/storage/browser/storageService.ts
@@ -17,6 +17,7 @@ import { AbstractStorageService, isProfi
@@ -18,6 +18,7 @@ import { AbstractStorageService, isProfi
import { isUserDataProfile, IUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
import { IAnyWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
import { IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
@@ -21,7 +21,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/storage/browser/storageS
export class BrowserStorageService extends AbstractStorageService {
@@ -297,7 +298,11 @@ export class IndexedDBStorageDatabase ex
@@ -298,7 +299,11 @@ export class IndexedDBStorageDatabase ex
}
static async createWorkspaceStorage(workspaceId: string, logService: ILogService): Promise<IIndexedDBStorageDatabase> {

View File

@@ -70,12 +70,12 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy"
- content="default-src 'none'; script-src 'sha256-QA1gXilHYAUFCvp7MpjgcmyBCFzSKV0SpiecMU8aUVc=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
+ content="default-src 'none'; script-src 'sha256-5X5RiKYn8NTJVx919WStPrAmsV80rIIBbePhKquPcAQ=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
- content="default-src 'none'; script-src 'sha256-frEVWVmmI4TWHGHXZaCTWqGQI9jv+i8hv+sOa87Gqlc=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
+ content="default-src 'none'; script-src 'sha256-1BNp/IJ0Swu9k0gYe2BJz18zVYJ4emIdN3fjPgGScQI=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
<!-- Disable pinch zooming -->
<meta name="viewport"
@@ -335,6 +335,12 @@
@@ -339,6 +339,12 @@
const hostname = location.hostname;
@@ -92,7 +92,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
@@ -334,6 +334,12 @@
@@ -338,6 +338,12 @@
const hostname = location.hostname;
@@ -113,8 +113,8 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWor
<meta http-equiv="Content-Security-Policy" content="
default-src 'none';
child-src 'self' data: blob:;
- script-src 'self' 'unsafe-eval' 'sha256-/r7rqQ+yrxt57sxLuQ6AMYcy/lUpvAIzHjIJt/OeLWU=' https:;
+ script-src 'self' 'unsafe-eval' 'sha256-TkIM/TmudlFEe0ZRp0ptvN54LClwk30Rql4ZPE0hm/I=' https:;
- script-src 'self' 'unsafe-eval' 'sha256-75NYUUvf+5++1WbfCZOV3PSWxBhONpaxwx+mkOFRv/Y=' https:;
+ script-src 'self' 'unsafe-eval' 'sha256-c7vPrYRaSLDtFSrI4CuHYgBQ3a4c4x2LSm/LefSZADQ=' https:;
connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*;"/>
</head>
<body>

View File

@@ -48,6 +48,7 @@ export interface UserProvidedCodeArgs {
"github-auth"?: string
"disable-update-check"?: boolean
"disable-file-downloads"?: boolean
"disable-file-uploads"?: boolean
"disable-workspace-trust"?: boolean
"disable-getting-started-override"?: boolean
"disable-proxy"?: boolean
@@ -170,6 +171,10 @@ export const options: Options<Required<UserProvidedArgs>> = {
description:
"Disable file downloads from Code. This can also be set with CS_DISABLE_FILE_DOWNLOADS set to 'true' or '1'.",
},
"disable-file-uploads": {
type: "boolean",
description: "Disable file uploads.",
},
"disable-workspace-trust": {
type: "boolean",
description: "Disable Workspace Trust feature. This switch only affects the current session.",

View File

@@ -31,7 +31,7 @@ export class Heart {
return
}
logger.trace("heartbeat")
logger.debug("heartbeat")
this.lastHeartbeat = Date.now()
if (typeof this.heartbeatTimer !== "undefined") {
clearTimeout(this.heartbeatTimer)

View File

@@ -109,7 +109,7 @@ export const runCodeServer = async (
logger.info(`code-server ${version} ${commit}`)
logger.info(`Using user-data-dir ${args["user-data-dir"]}`)
logger.trace(`Using extensions-dir ${args["extensions-dir"]}`)
logger.debug(`Using extensions-dir ${args["extensions-dir"]}`)
if (args.auth === AuthType.Password && !args.password && !args["hashed-password"]) {
throw new Error(

View File

@@ -23,6 +23,41 @@ describe("Downloads (enabled)", ["--disable-workspace-trust"], {}, async () => {
expect(await codeServerPage.page.isVisible("text=Download...")).toBe(true)
})
test("should see the 'Show Local' button on Save As", async ({ codeServerPage }) => {
// Setup
const workspaceDir = await codeServerPage.workspaceDir
const fileName = "unique-file-save-as.txt"
const tmpFilePath = path.join(workspaceDir, fileName)
await fs.writeFile(tmpFilePath, "Hello World")
// Action
await codeServerPage.page.waitForSelector(`text=${fileName}`)
await codeServerPage.openFile(fileName)
await codeServerPage.page.click(".tab")
await codeServerPage.navigateMenus(["File", "Auto Save"])
await codeServerPage.page.keyboard.type("Making some edits.")
await codeServerPage.navigateMenus(["File", "Save As..."])
await codeServerPage.page.waitForSelector(".quick-input-widget")
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true)
})
test("should see the 'Show Local' button on Save File", async ({ codeServerPage }) => {
// Action
await codeServerPage.navigateMenus(["File", "New Text File"])
await codeServerPage.waitForTab("Untitled-1")
await codeServerPage.navigateMenus(["File", "Save"])
await codeServerPage.page.waitForSelector(".quick-input-widget")
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true)
})
test("should see the 'Show Local' button on Save Workspace As", async ({ codeServerPage }) => {
// Action
await codeServerPage.navigateMenus(["File", "Save Workspace As..."])
await codeServerPage.page.waitForSelector(".quick-input-widget")
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true)
})
})
describe("Downloads (disabled)", ["--disable-workspace-trust", "--disable-file-downloads"], {}, async () => {
@@ -35,7 +70,7 @@ describe("Downloads (disabled)", ["--disable-workspace-trust", "--disable-file-d
// Setup
const workspaceDir = await codeServerPage.workspaceDir
const tmpFilePath = path.join(workspaceDir, "unique-file.txt")
await fs.writeFile(tmpFilePath, "hello world")
await fs.writeFile(tmpFilePath, "Hello World")
// Action
const fileInExplorer = await codeServerPage.page.waitForSelector("text=unique-file.txt")
@@ -45,4 +80,35 @@ describe("Downloads (disabled)", ["--disable-workspace-trust", "--disable-file-d
expect(await codeServerPage.page.isVisible("text=Download...")).toBe(false)
})
test("should not see the 'Show Local' button on Save as", async ({ codeServerPage }) => {
// Setup
const workspaceDir = await codeServerPage.workspaceDir
const fileName = "unique-file-save-as.txt"
const tmpFilePath = path.join(workspaceDir, fileName)
await fs.writeFile(tmpFilePath, "Hello World")
// Action
await codeServerPage.page.waitForSelector(`text=${fileName}`)
await codeServerPage.openFile(fileName)
await codeServerPage.page.click(".tab")
await codeServerPage.navigateMenus(["File", "Save As..."])
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false)
})
test("should not see the 'Show Local' button on Save File", async ({ codeServerPage }) => {
// Action
await codeServerPage.navigateMenus(["File", "New Text File"])
await codeServerPage.waitForTab("Untitled-1")
await codeServerPage.navigateMenus(["File", "Save"])
await codeServerPage.page.waitForSelector(".quick-input-widget")
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false)
})
test("should not see the 'Show Local' button on Save Workspace As", async ({ codeServerPage }) => {
// Action
await codeServerPage.navigateMenus(["File", "Save Workspace As..."])
await codeServerPage.page.waitForSelector(".quick-input-widget")
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false)
})
})

View File

@@ -401,7 +401,7 @@ export class CodeServerPage {
* Open a file by using menus.
*/
async openFile(file: string) {
await this.navigateMenus(["File", "Open File"])
await this.navigateMenus(["File", "Open File..."])
await this.navigateQuickInput([path.basename(file)])
await this.waitForTab(file)
}
@@ -432,7 +432,7 @@ export class CodeServerPage {
* it then clicking the match from the results.
*/
async executeCommandViaMenus(command: string) {
await this.navigateMenus(["View", "Command Palette"])
await this.navigateMenus(["View", "Command Palette..."])
await this.page.keyboard.type(command)
@@ -488,19 +488,19 @@ export class CodeServerPage {
// splitting them into two steps each we can cancel before running the
// action.
steps.push({
fn: () => this.page.hover(`${selector} :text("${item}")`, { trial: true }),
fn: () => this.page.hover(`${selector} :text-is("${item}")`, { trial: true }),
name: `${item}:hover:trial`,
})
steps.push({
fn: () => this.page.hover(`${selector} :text("${item}")`, { force: true }),
fn: () => this.page.hover(`${selector} :text-is("${item}")`, { force: true }),
name: `${item}:hover:force`,
})
steps.push({
fn: () => this.page.click(`${selector} :text("${item}")`, { trial: true }),
fn: () => this.page.click(`${selector} :text-is("${item}")`, { trial: true }),
name: `${item}:click:trial`,
})
steps.push({
fn: () => this.page.click(`${selector} :text("${item}")`, { force: true }),
fn: () => this.page.click(`${selector} :text-is("${item}")`, { force: true }),
name: `${item}:click:force`,
})
}

61
test/e2e/uploads.test.ts Normal file
View File

@@ -0,0 +1,61 @@
import { promises as fs } from "fs"
import * as path from "path"
import { clean } from "../utils/helpers"
import { describe, test, expect } from "./baseFixture"
describe("Uploads (enabled)", ["--disable-workspace-trust"], {}, () => {
const testName = "uploads-enabled"
test.beforeAll(async () => {
await clean(testName)
})
test("should see the 'Upload...' option", async ({ codeServerPage }) => {
// Setup
const workspaceDir = await codeServerPage.workspaceDir
const tmpDirPath = path.join(workspaceDir, "test-directory")
await fs.mkdir(tmpDirPath)
// Action
const fileInExplorer = await codeServerPage.page.waitForSelector('span:has-text("test-directory")')
await fileInExplorer.click({
button: "right",
})
expect(await codeServerPage.page.isVisible("text=Upload...")).toBe(true)
})
test("should see the 'Show Local' button on Open File", async ({ codeServerPage }) => {
// Action
await codeServerPage.navigateMenus(["File", "Open File..."])
await codeServerPage.page.waitForSelector(".quick-input-widget")
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true)
})
})
describe("Uploads (disabled)", ["--disable-workspace-trust", "--disable-file-uploads"], {}, () => {
const testName = "uploads-disabled"
test.beforeAll(async () => {
await clean(testName)
})
test("should not see the 'Upload...' option", async ({ codeServerPage }) => {
// Setup
const workspaceDir = await codeServerPage.workspaceDir
const tmpDirPath = path.join(workspaceDir, "test-directory")
await fs.mkdir(tmpDirPath)
// Action
const fileInExplorer = await codeServerPage.page.waitForSelector('span:has-text("test-directory")')
await fileInExplorer.click({
button: "right",
})
expect(await codeServerPage.page.isVisible("text=Upload...")).toBe(false)
})
test("should not see the 'Show Local' button on Open File", async ({ codeServerPage }) => {
// Action
await codeServerPage.navigateMenus(["File", "Open File..."])
await codeServerPage.page.waitForSelector(".quick-input-widget")
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false)
})
})