diff --git a/lib/vscode b/lib/vscode index 30d9c6cd..2062a59c 160000 --- a/lib/vscode +++ b/lib/vscode @@ -1 +1 @@ -Subproject commit 30d9c6cd9483b2cc586687151bcbcd635f373630 +Subproject commit 2062a59ca1a586d8a6e7bf483841085a94c440a4 diff --git a/patches/base-path.diff b/patches/base-path.diff index 49cef29f..867d43ab 100644 --- a/patches/base-path.diff +++ b/patches/base-path.diff @@ -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 -@@ -157,7 +157,9 @@ class RemoteAuthoritiesImpl { +@@ -162,7 +162,9 @@ class RemoteAuthoritiesImpl { return URI.from({ scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource, authority: `${host}:${port}`, @@ -118,26 +118,25 @@ 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 -@@ -267,14 +267,10 @@ export class WebClientServer { +@@ -267,12 +267,11 @@ export class WebClientServer { return res.end(); } -- let originalHost = req.headers['x-original-host']; -- if (Array.isArray(originalHost)) { -- originalHost = originalHost[0]; -- } -- const remoteAuthority = originalHost || req.headers.host; -- if (!remoteAuthority) { -- return serveError(req, res, 400, `Bad request.`); -- } -+ // It is not possible to reliably detect the remote authority on the server -+ // in all cases. Set this to something invalid to make sure we catch code -+ // that is using this when it should not. +- const getFirstHeader = (headerName: string) => { +- const val = req.headers[headerName]; +- return Array.isArray(val) ? val[0] : val; +- }; +- +- const remoteAuthority = getFirstHeader('x-original-host') || getFirstHeader('x-forwarded-host') || req.headers.host; ++ // For now we are getting the remote authority from the client to avoid ++ // needing specific configuration for reverse proxies to work. Set this to ++ // something invalid to make sure we catch code that is using this value ++ // from the backend when it should not. + const remoteAuthority = 'remote'; - - function asJSON(value: unknown): string { - return JSON.stringify(value).replace(/"/g, '"'); -@@ -297,6 +293,8 @@ export class WebClientServer { + if (!remoteAuthority) { + return serveError(req, res, 400, `Bad request.`); + } +@@ -298,6 +297,8 @@ export class WebClientServer { scopes: [['user:email'], ['repo']] } : undefined; @@ -146,7 +145,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts const workbenchWebConfiguration = { remoteAuthority, -@@ -308,6 +306,7 @@ export class WebClientServer { +@@ -309,6 +310,7 @@ export class WebClientServer { workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']), productConfiguration: >{ codeServerVersion: this._productService.codeServerVersion, @@ -154,20 +153,29 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts embedderIdentifier: 'server-distro', extensionsGallery: this._webExtensionResourceUrlTemplate ? { ...this._productService.extensionsGallery, -@@ -328,8 +327,10 @@ export class WebClientServer { +@@ -326,8 +328,10 @@ export class WebClientServer { const values: { [key: string]: string } = { WORKBENCH_WEB_CONFIGURATION: asJSON(workbenchWebConfiguration), WORKBENCH_AUTH_SESSION: authSessionInfo ? asJSON(authSessionInfo) : '', - WORKBENCH_WEB_BASE_URL: this._staticRoute, -- WORKBENCH_NLS_BASE_URL: nlsBaseUrl ? `${nlsBaseUrl}${this._productService.commit}/${this._productService.version}/` : '', +- WORKBENCH_NLS_BASE_URL: nlsBaseUrl ? `${nlsBaseUrl}${!nlsBaseUrl.endsWith('/') ? '/' : ''}${this._productService.commit}/${this._productService.version}/` : '', + WORKBENCH_WEB_BASE_URL: vscodeBase + this._staticRoute, -+ WORKBENCH_NLS_BASE_URL: vscodeBase + (nlsBaseUrl ? `${nlsBaseUrl}${this._productService.commit}/${this._productService.version}/` : ''), ++ WORKBENCH_NLS_BASE_URL: vscodeBase + (nlsBaseUrl ? `${nlsBaseUrl}${!nlsBaseUrl.endsWith('/') ? '/' : ''}${this._productService.commit}/${this._productService.version}/` : ''), + BASE: base, + VS_BASE: vscodeBase, }; -@@ -419,3 +420,70 @@ export class WebClientServer { +@@ -344,7 +348,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=' 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=';`, // 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:;', +@@ -417,3 +421,70 @@ export class WebClientServer { return res.end(data); } } diff --git a/patches/cli-window-open.diff b/patches/cli-window-open.diff index 966e313a..6c7621cb 100644 --- a/patches/cli-window-open.diff +++ b/patches/cli-window-open.diff @@ -26,7 +26,7 @@ Index: code-server/lib/vscode/src/vs/server/node/remoteTerminalChannel.ts readonly onExecuteCommand = this._onExecuteCommand.event; constructor( -@@ -240,20 +240,20 @@ export class RemoteTerminalChannel exten +@@ -241,20 +241,20 @@ export class RemoteTerminalChannel exten const ipcHandlePath = createRandomIPCHandle(); env.VSCODE_IPC_HOOK_CLI = ipcHandlePath; const commandsExecuter: ICommandsExecuter = { @@ -52,7 +52,7 @@ Index: code-server/lib/vscode/src/vs/server/node/remoteTerminalChannel.ts let resolve!: (data: any) => void; let reject!: (err: any) => void; const result = new Promise((_resolve, _reject) => { -@@ -276,6 +276,7 @@ export class RemoteTerminalChannel exten +@@ -277,6 +277,7 @@ export class RemoteTerminalChannel exten }); this._onExecuteCommand.fire({ reqId, diff --git a/patches/disable-builtin-ext-update.diff b/patches/disable-builtin-ext-update.diff index cbfd7740..bb2ee4a9 100644 --- a/patches/disable-builtin-ext-update.diff +++ b/patches/disable-builtin-ext-update.diff @@ -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 -@@ -234,6 +234,10 @@ export class Extension implements IExten +@@ -237,6 +237,10 @@ export class Extension implements IExten if (this.type === ExtensionType.System && this.productService.quality === 'stable') { return false; } @@ -18,7 +18,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens if (!this.local.preRelease && this.gallery.properties.isPreReleaseVersion) { return false; } -@@ -1088,6 +1092,10 @@ export class ExtensionsWorkbenchService +@@ -1122,6 +1126,10 @@ export class ExtensionsWorkbenchService // Skip if check updates only for builtin extensions and current extension is not builtin. continue; } diff --git a/patches/disable-downloads.diff b/patches/disable-downloads.diff index b5f7dc72..3ed71ac8 100644 --- a/patches/disable-downloads.diff +++ b/patches/disable-downloads.diff @@ -12,7 +12,7 @@ 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 -@@ -250,6 +250,11 @@ export interface IWorkbenchConstructionO +@@ -267,6 +267,11 @@ export interface IWorkbenchConstructionO */ readonly userDataPath?: string @@ -52,7 +52,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi + } + @memoize - get settingsResource(): URI { return joinPath(this.userRoamingDataHome, 'settings.json'); } + get argvResource(): URI { return joinPath(this.userRoamingDataHome, 'argv.json'); } Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts =================================================================== @@ -66,7 +66,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts /* ----- server setup ----- */ -@@ -94,6 +95,7 @@ export interface ServerParsedArgs { +@@ -95,6 +96,7 @@ export interface ServerParsedArgs { /* ----- code-server ----- */ 'disable-update-check'?: boolean; 'auth'?: string @@ -78,7 +78,7 @@ 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 -@@ -300,6 +300,7 @@ export class WebClientServer { +@@ -304,6 +304,7 @@ export class WebClientServer { remoteAuthority, webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre', userDataPath: this._environmentService.userDataPath, @@ -93,7 +93,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts @@ -7,12 +7,11 @@ import { Event } from 'vs/base/common/ev import { Disposable } from 'vs/base/common/lifecycle'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; - import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext } from 'vs/platform/contextkey/common/contextkeys'; + import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext } from 'vs/platform/contextkey/common/contextkeys'; -import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext } from 'vs/workbench/common/contextkeys'; +import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, IsEnabledFileDownloads } from 'vs/workbench/common/contextkeys'; import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, DEFAULT_EDITOR_ASSOCIATION } from 'vs/workbench/common/editor'; @@ -104,24 +104,24 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { WorkbenchState, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchLayoutService, Parts, positionToString } from 'vs/workbench/services/layout/browser/layoutService'; -@@ -24,6 +23,7 @@ import { IEditorResolverService } from ' - import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; +@@ -25,6 +24,7 @@ import { IPaneCompositePartService } fro import { Schemas } from 'vs/base/common/network'; import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess'; -+import { IBrowserWorkbenchEnvironmentService } from '../services/environment/browser/environmentService'; + import { IProductService } from 'vs/platform/product/common/productService'; ++import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService'; export class WorkbenchContextKeysHandler extends Disposable { private inputFocusedContext: IContextKey; -@@ -75,7 +75,7 @@ export class WorkbenchContextKeysHandler +@@ -76,7 +76,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, - @IEditorGroupsService private readonly editorGroupService: IEditorGroupsService, -@@ -194,6 +194,9 @@ export class WorkbenchContextKeysHandler +@@ -199,6 +199,9 @@ export class WorkbenchContextKeysHandler this.auxiliaryBarVisibleContext = AuxiliaryBarVisibleContext.bindTo(this.contextKeyService); this.auxiliaryBarVisibleContext.set(this.layoutService.isVisible(Parts.AUXILIARYBAR_PART)); diff --git a/patches/display-language.diff b/patches/display-language.diff index a0431baa..6bfec9e9 100644 --- a/patches/display-language.diff +++ b/patches/display-language.diff @@ -5,19 +5,21 @@ We can remove this once upstream supports all language packs. 1. Proxies language packs to the service on the backend. 2. NLS configuration is embedded into the HTML for the browser to pick up. This code to generate this configuration is copied from the native portion. -3. Remove navigator.language default since that will prevent the argv file from - being created if you are changing the language to whatever your browser - default happens to be. +3. Remove configuredLocale since we have our own thing. 4. Move the argv.json file to the server instead of in-browser storage. This is where the current locale is stored and currently the server needs to be able to read it. 5. Add the locale flag. +6. Remove the redundant locale verification. It does the same as the existing + one but is worse because it does not handle non-existent or empty files. +7. Replace some caching and Node requires because code-server does not restart + when changing the language unlike native Code. Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts +++ code-server/lib/vscode/src/vs/server/node/serverServices.ts -@@ -202,6 +202,9 @@ export async function setupServerService +@@ -212,6 +212,9 @@ export async function setupServerService const channel = new ExtensionManagementChannel(extensionManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority)); socketServer.registerChannel('extensions', channel); @@ -31,14 +33,31 @@ Index: code-server/lib/vscode/src/vs/base/common/platform.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/base/common/platform.ts +++ code-server/lib/vscode/src/vs/base/common/platform.ts -@@ -80,8 +80,19 @@ if (typeof navigator === 'object' && !is - _isIOS = (_userAgent.indexOf('Macintosh') >= 0 || _userAgent.indexOf('iPad') >= 0 || _userAgent.indexOf('iPhone') >= 0) && !!navigator.maxTouchPoints && navigator.maxTouchPoints > 0; +@@ -2,8 +2,6 @@ + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +-import * as nls from 'vs/nls'; +- + const LANGUAGE_DEFAULT = 'en'; + + let _isWindows = false; +@@ -81,17 +79,19 @@ if (typeof navigator === 'object' && !is _isLinux = _userAgent.indexOf('Linux') >= 0; _isWeb = true; -- _locale = navigator.language; + +- const configuredLocale = nls.getConfiguredDefaultLocale( +- // This call _must_ be done in the file that calls `nls.getConfiguredDefaultLocale` +- // to ensure that the NLS AMD Loader plugin has been loaded and configured. +- // This is because the loader plugin decides what the default locale is based on +- // how it's able to resolve the strings. +- nls.localize({ key: 'ensureLoaderPluginIsLoaded', comment: ['{Locked}'] }, '_') +- ); +- +- _locale = configuredLocale || LANGUAGE_DEFAULT; + _locale = LANGUAGE_DEFAULT; + _language = _locale; -+ + const el = typeof document !== 'undefined' && document.getElementById('vscode-remote-nls-configuration'); + const rawNlsConfig = el && el.getAttribute('data-settings'); + if (rawNlsConfig) { @@ -66,21 +85,19 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html -@@ -43,17 +46,27 @@ - self.webPackagePaths[key] = `${baseUrl}/node_modules/${key}/${self.webPackagePaths[key]}`; - }); - -- // Set up nls if the user is not using the default language (English) +@@ -46,15 +49,26 @@ + // Set up nls if the user is not using the default language (English) const nlsConfig = {}; -- const locale = navigator.language; + const locale = window.localStorage.getItem('vscode.nls.locale') || navigator.language; - if (!locale.startsWith('en')) { - nlsConfig['vs/nls'] = { - availableLanguages: { - '*': locale - }, -- baseUrl: '{{WORKBENCH_NLS_BASE_URL}}' +- 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) { @@ -101,14 +118,14 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html + } + } + } catch (error) { /* Probably fine. */ } - require.config({ baseUrl: `${baseUrl}/out`, + recordStats: true, Index: code-server/lib/vscode/src/vs/platform/environment/common/environmentService.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/platform/environment/common/environmentService.ts +++ code-server/lib/vscode/src/vs/platform/environment/common/environmentService.ts -@@ -108,7 +108,7 @@ export abstract class AbstractNativeEnvi +@@ -105,7 +105,7 @@ export abstract class AbstractNativeEnvi return URI.file(join(vscodePortable, 'argv.json')); } @@ -190,7 +207,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'; -@@ -295,6 +296,8 @@ export class WebClientServer { +@@ -299,6 +300,8 @@ export class WebClientServer { const base = relativeRoot(getOriginalUrl(req)) const vscodeBase = relativePath(getOriginalUrl(req)) @@ -199,8 +216,8 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts const workbenchWebConfiguration = { remoteAuthority, -@@ -338,6 +341,7 @@ export class WebClientServer { - WORKBENCH_NLS_BASE_URL: vscodeBase + (nlsBaseUrl ? `${nlsBaseUrl}${this._productService.commit}/${this._productService.version}/` : ''), +@@ -339,6 +342,7 @@ export class WebClientServer { + WORKBENCH_NLS_BASE_URL: vscodeBase + (nlsBaseUrl ? `${nlsBaseUrl}${!nlsBaseUrl.endsWith('/') ? '/' : ''}${this._productService.commit}/${this._productService.version}/` : ''), BASE: base, VS_BASE: vscodeBase, + NLS_CONFIGURATION: asJSON(nlsConfiguration), @@ -219,7 +236,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts /* ----- server setup ----- */ -@@ -96,6 +97,7 @@ export interface ServerParsedArgs { +@@ -97,6 +98,7 @@ export interface ServerParsedArgs { 'disable-update-check'?: boolean; 'auth'?: string 'disable-file-downloads'?: boolean; @@ -231,39 +248,85 @@ Index: code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/workbench.web.main.ts +++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts -@@ -109,6 +109,12 @@ registerSingleton(IDiagnosticsService, N +@@ -122,8 +122,9 @@ import 'vs/workbench/contrib/logs/browse + // Explorer + import 'vs/workbench/contrib/files/browser/files.web.contribution'; - //#region --- workbench contributions - -+// Localization. These do not actually import anything specific to Electron so -+// they should be safe. -+import 'vs/workbench/services/localization/electron-sandbox/localeService'; +-// Localization +-import 'vs/workbench/contrib/localization/browser/localization.contribution'; ++// Localization. This does not actually import anything specific to Electron so ++// it should be safe. +import 'vs/workbench/contrib/localization/electron-sandbox/localization.contribution'; -+import 'vs/platform/languagePacks/browser/languagePacks'; -+ - // Output - import 'vs/workbench/contrib/output/common/outputChannelModelService'; + // Performance + import 'vs/workbench/contrib/performance/browser/performance.web.contribution'; Index: code-server/lib/vscode/src/vs/platform/languagePacks/browser/languagePacks.ts =================================================================== ---- /dev/null +--- code-server.orig/lib/vscode/src/vs/platform/languagePacks/browser/languagePacks.ts +++ code-server/lib/vscode/src/vs/platform/languagePacks/browser/languagePacks.ts -@@ -0,0 +1,18 @@ +@@ -4,10 +4,23 @@ + *--------------------------------------------------------------------------------------------*/ + + import { ILanguagePackItem, LanguagePackBaseService } from 'vs/platform/languagePacks/common/languagePacks'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; -+import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks'; +import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; -+ -+// @ts-ignore: interface is implemented via proxy -+export class LanguagePackService implements ILanguagePackService { -+ -+ declare readonly _serviceBrand: undefined; ++import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement'; + + export class WebLanguagePacksService extends LanguagePackBaseService { +- // Web doesn't have a concept of language packs, so we just return an empty array ++ private readonly languagePackService: ILanguagePackService; + + constructor( + @IRemoteAgentService remoteAgentService: IRemoteAgentService, ++ @IExtensionGalleryService extensionGalleryService: IExtensionGalleryService + ) { -+ return ProxyChannel.toService(remoteAgentService.getConnection()!.getChannel('languagePacks')); ++ super(extensionGalleryService) ++ this.languagePackService = ProxyChannel.toService(remoteAgentService.getConnection()!.getChannel('languagePacks')); + } -+} + -+registerSingleton(ILanguagePackService, LanguagePackService, true); + getInstalledLanguages(): Promise { +- return Promise.resolve([]); ++ return this.languagePackService.getInstalledLanguages() + } + } +Index: code-server/lib/vscode/src/vs/workbench/contrib/localization/electron-sandbox/localeService.ts +=================================================================== +--- code-server.orig/lib/vscode/src/vs/workbench/contrib/localization/electron-sandbox/localeService.ts ++++ code-server/lib/vscode/src/vs/workbench/contrib/localization/electron-sandbox/localeService.ts +@@ -41,7 +41,8 @@ export class NativeLocaleService impleme + @IProductService private readonly productService: IProductService + ) { } + +- private async validateLocaleFile(): Promise { ++ // Make public just so we do not have to patch all the unused code out. ++ public async validateLocaleFile(): Promise { + try { + const content = await this.textFileService.read(this.environmentService.argvResource, { encoding: 'utf8' }); + +@@ -68,9 +69,6 @@ export class NativeLocaleService impleme + } + + private async writeLocaleValue(locale: string | undefined): Promise { +- if (!(await this.validateLocaleFile())) { +- return false; +- } + await this.jsonEditingService.write(this.environmentService.argvResource, [{ path: ['locale'], value: locale }], true); + return true; + } +Index: code-server/lib/vscode/src/vs/base/node/languagePacks.js +=================================================================== +--- code-server.orig/lib/vscode/src/vs/base/node/languagePacks.js ++++ code-server/lib/vscode/src/vs/base/node/languagePacks.js +@@ -73,7 +73,10 @@ + function getLanguagePackConfigurations(userDataPath) { + const configFile = path.join(userDataPath, 'languagepacks.json'); + try { +- return nodeRequire(configFile); ++ // This must not use Node's require otherwise it will be cached forever. ++ // Code can get away with this since the process actually restarts but ++ // that is not currently the case with code-server. ++ return JSON.parse(fs.readFileSync(configFile, "utf8")); + } catch (err) { + // Do nothing. If we can't read the file we have no + // language pack config. diff --git a/patches/insecure-notification.diff b/patches/insecure-notification.diff index 10183603..364ef175 100644 --- a/patches/insecure-notification.diff +++ b/patches/insecure-notification.diff @@ -20,7 +20,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts import { Disposable } from 'vs/base/common/lifecycle'; +import { localize } from 'vs/nls'; +import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; - + export class CodeServerClient extends Disposable { constructor ( + @INotificationService private notificationService: INotificationService, diff --git a/patches/integration.diff b/patches/integration.diff index f3d63771..fd1fb03f 100644 --- a/patches/integration.diff +++ b/patches/integration.diff @@ -184,7 +184,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IProgressService } from 'vs/platform/progress/common/progress'; import { DelayedLogChannel } from 'vs/workbench/services/output/common/delayedLogChannel'; -@@ -109,6 +110,9 @@ export class BrowserMain extends Disposa +@@ -116,6 +117,9 @@ export class BrowserMain extends Disposa // Startup const instantiationService = workbench.startup(); @@ -263,7 +263,7 @@ 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 -@@ -307,6 +307,7 @@ export class WebClientServer { +@@ -308,6 +308,7 @@ export class WebClientServer { folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']), workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']), productConfiguration: >{ diff --git a/patches/local-storage.diff b/patches/local-storage.diff index a7aa8b06..fe0b59c0 100644 --- a/patches/local-storage.diff +++ b/patches/local-storage.diff @@ -20,7 +20,7 @@ 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 -@@ -299,6 +299,7 @@ export class WebClientServer { +@@ -303,6 +303,7 @@ export class WebClientServer { const workbenchWebConfiguration = { remoteAuthority, webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre', @@ -32,7 +32,7 @@ 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 -@@ -245,6 +245,11 @@ export interface IWorkbenchConstructionO +@@ -262,6 +262,11 @@ export interface IWorkbenchConstructionO */ readonly configurationDefaults?: Record; @@ -63,4 +63,4 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi + } @memoize - get settingsResource(): URI { return joinPath(this.userRoamingDataHome, 'settings.json'); } + get argvResource(): URI { return joinPath(this.userRoamingDataHome, 'argv.json'); } diff --git a/patches/log-level.diff b/patches/log-level.diff index 53226c22..5961f989 100644 --- a/patches/log-level.diff +++ b/patches/log-level.diff @@ -7,7 +7,7 @@ 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 -@@ -300,7 +300,10 @@ export class WebClientServer { +@@ -304,7 +304,10 @@ export class WebClientServer { remoteAuthority, webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre', _wrapWebWorkerExtHostInIframe, diff --git a/patches/logout.diff b/patches/logout.diff index 7b3fa1cb..999ebdf0 100644 --- a/patches/logout.diff +++ b/patches/logout.diff @@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts /* ----- server setup ----- */ -@@ -92,6 +93,7 @@ export const serverOptions: OptionDescri +@@ -93,6 +94,7 @@ export const serverOptions: OptionDescri export interface ServerParsedArgs { /* ----- code-server ----- */ 'disable-update-check'?: boolean; @@ -40,7 +40,7 @@ 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 -@@ -309,6 +309,7 @@ export class WebClientServer { +@@ -313,6 +313,7 @@ export class WebClientServer { codeServerVersion: this._productService.codeServerVersion, rootEndpoint: base, updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined, diff --git a/patches/marketplace.diff b/patches/marketplace.diff index 8eb88101..d079d2b0 100644 --- a/patches/marketplace.diff +++ b/patches/marketplace.diff @@ -48,7 +48,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts } /** -@@ -308,14 +308,7 @@ export class WebClientServer { +@@ -312,14 +312,7 @@ export class WebClientServer { codeServerVersion: this._productService.codeServerVersion, rootEndpoint: base, embedderIdentifier: 'server-distro', diff --git a/patches/proposed-api.diff b/patches/proposed-api.diff index 397a3767..904ef7d2 100644 --- a/patches/proposed-api.diff +++ b/patches/proposed-api.diff @@ -9,7 +9,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/abstra =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts -@@ -1451,7 +1451,7 @@ class ProposedApiController { +@@ -1460,7 +1460,7 @@ class ProposedApiController { this._envEnabledExtensions = new Set((_environmentService.extensionEnabledProposedApi ?? []).map(id => ExtensionIdentifier.toKey(id))); diff --git a/patches/proxy-uri.diff b/patches/proxy-uri.diff index d606515d..a8341455 100644 --- a/patches/proxy-uri.diff +++ b/patches/proxy-uri.diff @@ -32,7 +32,7 @@ Index: code-server/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityReso import { IProductService } from 'vs/platform/product/common/productService'; -import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver'; +import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolvedOptions, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver'; - import { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts'; + import { getRemoteServerRootPath, parseAuthorityWithOptionalPort } from 'vs/platform/remote/common/remoteHosts'; export class RemoteAuthorityResolverService extends Disposable implements IRemoteAuthorityResolverService { @@ -22,7 +22,7 @@ export class RemoteAuthorityResolverServ @@ -44,23 +44,19 @@ Index: code-server/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityReso super(); this._cache = new Map(); this._connectionToken = connectionToken; -@@ -62,12 +62,17 @@ export class RemoteAuthorityResolverServ +@@ -62,9 +62,14 @@ export class RemoteAuthorityResolverServ private _doResolveAuthority(authority: string): ResolverResult { const connectionToken = this._connectionTokens.get(authority) || this._connectionToken; -+ let options: ResolvedOptions | undefined ++ let options: ResolvedOptions | undefined; + if (this.proxyEndpointTemplate) { + const proxyUrl = new URL(this.proxyEndpointTemplate, window.location.href); + options = { extensionHostEnv: { VSCODE_PROXY_URI: decodeURIComponent(proxyUrl.toString()) }} + } - if (authority.indexOf(':') >= 0) { - const pieces = authority.split(':'); -- return { authority: { authority, host: pieces[0], port: parseInt(pieces[1], 10), connectionToken } }; -+ return { authority: { authority, host: pieces[0], port: parseInt(pieces[1], 10), connectionToken }, options }; - } - const port = (/^https:/.test(window.location.href) ? 443 : 80); -- return { authority: { authority, host: authority, port: port, connectionToken } }; -+ return { authority: { authority, host: authority, port: port, connectionToken }, options }; + const defaultPort = (/^https:/.test(window.location.href) ? 443 : 80); + const { host, port } = parseAuthorityWithOptionalPort(authority, defaultPort); +- return { authority: { authority, host: host, port: port, connectionToken } }; ++ return { authority: { authority, host: host, port: port, connectionToken }, options }; } _clearResolvedAuthority(authority: string): void { @@ -68,7 +64,7 @@ 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 -@@ -310,6 +310,7 @@ export class WebClientServer { +@@ -314,6 +314,7 @@ export class WebClientServer { rootEndpoint: base, updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined, logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined, @@ -80,7 +76,7 @@ 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 -@@ -209,7 +209,7 @@ export class BrowserMain extends Disposa +@@ -239,7 +239,7 @@ export class BrowserMain extends Disposa // Remote const connectionToken = environmentService.options.connectionToken || getCookieValue(connectionTokenCookieName); diff --git a/patches/service-worker.diff b/patches/service-worker.diff index 523c60da..8d39a827 100644 --- a/patches/service-worker.diff +++ b/patches/service-worker.diff @@ -21,7 +21,7 @@ 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 -@@ -315,6 +315,10 @@ export class WebClientServer { +@@ -319,6 +319,10 @@ export class WebClientServer { updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined, logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined, proxyEndpointTemplate: base + '/proxy/{{port}}', diff --git a/patches/store-socket.diff b/patches/store-socket.diff index 5aa40ec6..74a7b635 100644 --- a/patches/store-socket.diff +++ b/patches/store-socket.diff @@ -24,7 +24,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService. import * as performance from 'vs/base/common/performance'; import { createApiFactoryAndRegisterActors } from 'vs/workbench/api/common/extHost.api.impl'; import { RequireInterceptor } from 'vs/workbench/api/common/extHostRequireInterceptor'; -@@ -69,6 +71,10 @@ export class ExtHostExtensionService ext +@@ -72,6 +74,10 @@ export class ExtHostExtensionService ext if (this._initData.remote.isRemote && this._initData.remote.authority) { const cliServer = this._instaService.createInstance(CLIServer); process.env['VSCODE_IPC_HOOK_CLI'] = cliServer.ipcHandlePath; diff --git a/patches/telemetry.diff b/patches/telemetry.diff index 77b5064b..4d0914f5 100644 --- a/patches/telemetry.diff +++ b/patches/telemetry.diff @@ -4,124 +4,47 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts +++ code-server/lib/vscode/src/vs/server/node/serverServices.ts -@@ -70,6 +70,7 @@ import { REMOTE_FILE_SYSTEM_CHANNEL_NAME - import { ExtensionHostStatusService, IExtensionHostStatusService } from 'vs/server/node/extensionHostStatusService'; - import { IExtensionsScannerService } from 'vs/platform/extensionManagement/common/extensionsScannerService'; +@@ -71,6 +71,7 @@ import { IExtensionsScannerService } fro import { ExtensionsScannerService } from 'vs/server/node/extensionsScannerService'; + import { ExtensionsProfileScannerService, IExtensionsProfileScannerService } from 'vs/platform/extensionManagement/common/extensionsProfileScannerService'; + import { IUserDataProfilesService, UserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile'; +import { TelemetryClient } from "vs/server/node/telemetryClient"; import { NullPolicyService } from 'vs/platform/policy/common/policy'; + import { OneDataSystemAppender } from 'vs/platform/telemetry/node/1dsAppender'; - const eventPrefix = 'monacoworkbench'; -@@ -123,7 +124,11 @@ export async function setupServerService - let appInsightsAppender: ITelemetryAppender = NullAppender; +@@ -133,10 +134,13 @@ export async function setupServerService const machineId = await getMachineId(); + const isInternal = isInternalTelemetry(productService, configurationService); if (supportsTelemetry(productService, environmentService)) { -- if (productService.aiConfig && productService.aiConfig.asimovKey) { +- if (productService.aiConfig && productService.aiConfig.ariaKey) { + const telemetryEndpoint = process.env.CS_TELEMETRY_URL || "https://v1.telemetry.coder.com/track"; + if (telemetryEndpoint) { -+ appInsightsAppender = new AppInsightsAppender(eventPrefix, null, () => new TelemetryClient(telemetryEndpoint) as any); -+ disposables.add(toDisposable(() => appInsightsAppender!.flush())); // Ensure the AI appender is disposed so that it flushes remaining data -+ } else if (productService.aiConfig && productService.aiConfig.asimovKey) { - appInsightsAppender = new AppInsightsAppender(eventPrefix, null, productService.aiConfig.asimovKey); - disposables.add(toDisposable(() => appInsightsAppender!.flush())); // Ensure the AI appender is disposed so that it flushes remaining data ++ oneDsAppender = new OneDataSystemAppender(false, eventPrefix, null, () => new TelemetryClient(telemetryEndpoint)); ++ } else if (productService.aiConfig && productService.aiConfig.ariaKey) { + oneDsAppender = new OneDataSystemAppender(isInternal, eventPrefix, null, productService.aiConfig.ariaKey); +- disposables.add(toDisposable(() => oneDsAppender?.flush())); // Ensure the AI appender is disposed so that it flushes remaining data } ++ disposables.add(toDisposable(() => oneDsAppender?.flush())); // Ensure the AI appender is disposed so that it flushes remaining data + + const config: ITelemetryServiceConfig = { + appenders: [oneDsAppender], Index: code-server/lib/vscode/src/vs/server/node/telemetryClient.ts =================================================================== --- /dev/null +++ code-server/lib/vscode/src/vs/server/node/telemetryClient.ts -@@ -0,0 +1,135 @@ -+import * as appInsights from 'applicationinsights'; +@@ -0,0 +1,49 @@ ++import { AppInsightsCore, IExtendedTelemetryItem, ITelemetryItem } from '@microsoft/1ds-core-js'; +import * as https from 'https'; +import * as http from 'http'; +import * as os from 'os'; + -+class Channel { -+ public get _sender() { -+ throw new Error('unimplemented'); -+ } -+ public get _buffer() { -+ throw new Error('unimplemented'); -+ } -+ -+ public setUseDiskRetryCaching(): void { -+ throw new Error('unimplemented'); -+ } -+ public send(): void { -+ throw new Error('unimplemented'); -+ } -+ public triggerSend(): void { -+ throw new Error('unimplemented'); -+ } -+} -+ -+// Unable to use implements because TypeScript tells you a private property is -+// missing but if you add it then it complains they have different private -+// properties. Uncommenting it during development can be helpful though to see -+// if anything is missing. -+export class TelemetryClient /* implements appInsights.TelemetryClient */ { -+ private _telemetryProcessors: any = undefined; -+ public context: any = undefined; -+ public commonProperties: any = undefined; -+ public config: any = {}; -+ public quickPulseClient: any = undefined; -+ -+ public channel: any = new Channel(); -+ ++export class TelemetryClient extends AppInsightsCore { + public constructor(private readonly endpoint: string) { -+ // Nothing to do. ++ super(); + } + -+ public addTelemetryProcessor(): void { -+ throw new Error('unimplemented'); -+ } -+ -+ public clearTelemetryProcessors(): void { -+ if (this._telemetryProcessors) { -+ this._telemetryProcessors = undefined; -+ } -+ } -+ -+ public runTelemetryProcessors(): void { -+ throw new Error('unimplemented'); -+ } -+ -+ public trackTrace(): void { -+ throw new Error('unimplemented'); -+ } -+ -+ public trackMetric(): void { -+ throw new Error('unimplemented'); -+ } -+ -+ public trackException(): void { -+ throw new Error('unimplemented'); -+ } -+ -+ public trackRequest(): void { -+ throw new Error('unimplemented'); -+ } -+ -+ public trackDependency(): void { -+ throw new Error('unimplemented'); -+ } -+ -+ public track(): void { -+ throw new Error('unimplemented'); -+ } -+ -+ public trackNodeHttpRequestSync(): void { -+ throw new Error('unimplemented'); -+ } -+ -+ public trackNodeHttpRequest(): void { -+ throw new Error('unimplemented'); -+ } -+ -+ public trackNodeHttpDependency(): void { -+ throw new Error('unimplemented'); -+ } -+ -+ public trackEvent(options: appInsights.Contracts.EventTelemetry): void { ++ public override track(item: IExtendedTelemetryItem | ITelemetryItem): void { ++ const options = item.baseData || {} + if (!options.properties) { + options.properties = {}; + } @@ -158,51 +81,63 @@ Index: code-server/lib/vscode/src/vs/server/node/telemetryClient.ts + request.end(); + } catch (error) {} + } -+ -+ public flush(options: { callback: (v: string) => void }): void { -+ if (options.callback) { -+ options.callback(''); -+ } -+ } +} Index: code-server/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts +++ code-server/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts -@@ -120,16 +120,19 @@ export class TelemetryService extends Di +@@ -38,26 +38,30 @@ export class TelemetryService extends Di ) { super(); -- if (supportsTelemetry(productService, environmentService) && productService.aiConfig?.asimovKey) { +- if (supportsTelemetry(productService, environmentService) && productService.aiConfig?.ariaKey) { + if (supportsTelemetry(productService, environmentService)) { // If remote server is present send telemetry through that, else use the client side appender -- const telemetryProvider: ITelemetryAppender = remoteAgentService.getConnection() !== null ? { log: remoteAgentService.logTelemetry.bind(remoteAgentService), flush: remoteAgentService.flushTelemetry.bind(remoteAgentService) } : new WebAppInsightsAppender('monacoworkbench', productService.aiConfig?.asimovKey); + const appenders = []; + const isInternal = isInternalTelemetry(productService, configurationService); +- const telemetryProvider: ITelemetryAppender = remoteAgentService.getConnection() !== null ? { log: remoteAgentService.logTelemetry.bind(remoteAgentService), flush: remoteAgentService.flushTelemetry.bind(remoteAgentService) } : new OneDataSystemWebAppender(isInternal, 'monacoworkbench', null, productService.aiConfig?.ariaKey); +- appenders.push(telemetryProvider); +- appenders.push(new TelemetryLogAppender(loggerService, environmentService)); - const config: ITelemetryServiceConfig = { -- appenders: [new WebTelemetryAppender(telemetryProvider), new TelemetryLogAppender(loggerService, environmentService)], -- commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.remoteAuthority, productService.embedderIdentifier, productService.removeTelemetryMachineId, environmentService.options && environmentService.options.resolveCommonTelemetryProperties), +- appenders, +- commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, isInternal, environmentService.remoteAuthority, productService.embedderIdentifier, productService.removeTelemetryMachineId, environmentService.options && environmentService.options.resolveCommonTelemetryProperties), - sendErrorTelemetry: this.sendErrorTelemetry, - }; -- - this.impl = this._register(new BaseTelemetryService(config, configurationService, productService)); -+ const telemetryProvider: ITelemetryAppender | undefined = remoteAgentService.getConnection() !== null ? { log: remoteAgentService.logTelemetry.bind(remoteAgentService), flush: remoteAgentService.flushTelemetry.bind(remoteAgentService) } : productService.aiConfig?.asimovKey ? new WebAppInsightsAppender('monacoworkbench', productService.aiConfig?.asimovKey) : undefined; ++ const telemetryProvider: ITelemetryAppender | undefined = remoteAgentService.getConnection() !== null ? { log: remoteAgentService.logTelemetry.bind(remoteAgentService), flush: remoteAgentService.flushTelemetry.bind(remoteAgentService) } : productService.aiConfig?.ariaKey ? new OneDataSystemWebAppender(isInternal, 'monacoworkbench', null, productService.aiConfig?.ariaKey) : undefined; + if (telemetryProvider) { ++ appenders.push(telemetryProvider); ++ appenders.push(new TelemetryLogAppender(loggerService, environmentService)); + const config: ITelemetryServiceConfig = { -+ appenders: [new WebTelemetryAppender(telemetryProvider), new TelemetryLogAppender(loggerService, environmentService)], -+ commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.remoteAuthority, productService.embedderIdentifier, productService.removeTelemetryMachineId, environmentService.options && environmentService.options.resolveCommonTelemetryProperties), ++ appenders, ++ commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, isInternal, environmentService.remoteAuthority, productService.embedderIdentifier, productService.removeTelemetryMachineId, environmentService.options && environmentService.options.resolveCommonTelemetryProperties), + sendErrorTelemetry: this.sendErrorTelemetry, + }; + this.impl = this._register(new BaseTelemetryService(config, configurationService, productService)); + +- if (getTelemetryLevel(configurationService) !== TelemetryLevel.NONE) { +- // If we cannot fetch the endpoint it means it is down and we should not send any telemetry. +- // This is most likely due to ad blockers +- fetch(telemetryEndpointUrl, { method: 'POST' }).catch(err => { +- this.impl = NullTelemetryService; +- }); ++ if (remoteAgentService.getConnection() === null && getTelemetryLevel(configurationService) !== TelemetryLevel.NONE) { ++ // If we cannot fetch the endpoint it means it is down and we should not send any telemetry. ++ // This is most likely due to ad blockers ++ fetch(telemetryEndpointUrl, { method: 'POST' }).catch(err => { ++ this.impl = NullTelemetryService; ++ }); ++ } + } else { + this.impl = NullTelemetryService; -+ } + } } else { this.impl = NullTelemetryService; - } 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 -@@ -320,6 +320,7 @@ export class WebClientServer { +@@ -324,6 +324,7 @@ export class WebClientServer { scope: vscodeBase + '/', path: base + '/_static/out/browser/serviceWorker.js', }, diff --git a/patches/unique-db.diff b/patches/unique-db.diff index ca3cc1af..a7b6e5ad 100644 --- a/patches/unique-db.diff +++ b/patches/unique-db.diff @@ -14,35 +14,37 @@ code-server. This has e2e tests. -Index: code-server/lib/vscode/src/vs/platform/storage/browser/storageService.ts +Index: code-server/lib/vscode/src/vs/workbench/services/storage/browser/storageService.ts =================================================================== ---- code-server.orig/lib/vscode/src/vs/platform/storage/browser/storageService.ts -+++ code-server/lib/vscode/src/vs/platform/storage/browser/storageService.ts -@@ -13,6 +13,7 @@ import { InMemoryStorageDatabase, isStor - import { ILogService } from 'vs/platform/log/common/log'; - import { AbstractStorageService, IS_NEW_KEY, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; +--- 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 + import { IUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile'; import { IAnyWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace'; + import { IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile'; +import { hash } from 'vs/base/common/hash'; export class BrowserStorageService extends AbstractStorageService { -@@ -36,7 +37,11 @@ export class BrowserStorageService exten +@@ -67,7 +68,11 @@ export class BrowserStorageService exten + return `global-${this.profileStorageProfile.id}`; + } + case StorageScope.WORKSPACE: +- return this.payload.id; ++ // Add a unique ID based on the current path for per-workspace databases. ++ // This prevents workspaces on different machines that share the same domain ++ // and file path from colliding (since it does not appear IndexedDB can be ++ // scoped to a path) as long as they are hosted on different paths. ++ return this.payload.id + '-' + hash(location.pathname.toString().replace(/\/$/, "")).toString(16); + } } - private getId(scope: StorageScope): string { -- return scope === StorageScope.GLOBAL ? 'global' : this.payload.id; -+ // Add a unique ID based on the current path for per-workspace databases. -+ // This prevents workspaces on different machines that share the same domain -+ // and file path from colliding (since it does not appear IndexedDB can be -+ // scoped to a path) as long as they are hosted on different paths. -+ return scope === StorageScope.GLOBAL ? 'global' : (this.payload.id + '-' + hash(location.pathname.toString().replace(/\/$/, "")).toString(16)); - } +@@ -141,6 +146,25 @@ export class BrowserStorageService exten - protected async doInitialize(): Promise { -@@ -75,6 +80,21 @@ export class BrowserStorageService exten - const firstWorkspaceOpen = this.workspaceStorage.getBoolean(IS_NEW_KEY); - if (firstWorkspaceOpen === undefined) { - this.workspaceStorage.set(IS_NEW_KEY, true); + await this.workspaceStorage.init(); + ++ const firstWorkspaceOpen = this.workspaceStorage.getBoolean(IS_NEW_KEY); ++ if (firstWorkspaceOpen === undefined) { + // Migrate the old database. + let db: IIndexedDBStorageDatabase | undefined + try { @@ -58,6 +60,8 @@ Index: code-server/lib/vscode/src/vs/platform/storage/browser/storageService.ts + db.close() + } + } - } else if (firstWorkspaceOpen) { - this.workspaceStorage.set(IS_NEW_KEY, false); - } ++ } ++ + this.updateIsNew(this.workspaceStorage); + } + diff --git a/patches/update-check.diff b/patches/update-check.diff index 941ffa16..63c55921 100644 --- a/patches/update-check.diff +++ b/patches/update-check.diff @@ -57,7 +57,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts + return; + } + -+ const lastNoti = this.storageService.getNumber('csLastUpdateNotification', StorageScope.GLOBAL); ++ const lastNoti = this.storageService.getNumber('csLastUpdateNotification', StorageScope.APPLICATION); + if (lastNoti) { + // Only remind them again after 1 week. + const timeout = 1000 * 60 * 60 * 24 * 7; @@ -67,7 +67,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts + } + } + -+ this.storageService.store('csLastUpdateNotification', Date.now(), StorageScope.GLOBAL, StorageTarget.MACHINE); ++ this.storageService.store('csLastUpdateNotification', Date.now(), StorageScope.APPLICATION, StorageTarget.MACHINE); + + this.notificationService.notify({ + severity: Severity.Info, @@ -105,7 +105,7 @@ 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 -@@ -308,6 +308,7 @@ export class WebClientServer { +@@ -312,6 +312,7 @@ export class WebClientServer { productConfiguration: >{ codeServerVersion: this._productService.codeServerVersion, rootEndpoint: base, @@ -126,7 +126,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts /* ----- server setup ----- */ -@@ -88,6 +90,8 @@ export const serverOptions: OptionDescri +@@ -89,6 +91,8 @@ export const serverOptions: OptionDescri }; export interface ServerParsedArgs { diff --git a/patches/webview.diff b/patches/webview.diff index 178dff9b..2c2c6925 100644 --- a/patches/webview.diff +++ b/patches/webview.diff @@ -24,7 +24,7 @@ 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 -@@ -183,7 +183,7 @@ export class BrowserWorkbenchEnvironment +@@ -177,7 +177,7 @@ export class BrowserWorkbenchEnvironment @memoize get webviewExternalEndpoint(): string { @@ -37,7 +37,7 @@ 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 -@@ -298,6 +298,7 @@ export class WebClientServer { +@@ -302,6 +302,7 @@ export class WebClientServer { const workbenchWebConfiguration = { remoteAuthority, @@ -53,8 +53,8 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index -+ content="default-src 'none'; script-src 'sha256-aOCIU83V9nV+0ERJudbrKLqgIVOHqU71i4Lv5urjGTI=' 'self'; frame-src 'self'; style-src 'unsafe-inline';"> +- content="default-src 'none'; script-src 'sha256-JpX/ganPoxpavjxWCz9DUZgwVZ59o2lwSYTQrziPsdU=' 'self'; frame-src 'self'; style-src 'unsafe-inline';"> ++ content="default-src 'none'; script-src 'sha256-BRi/ZOLWtsisl3jAheglVzKmoA1T6n2Mmf2NM4UnIXE=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">