From ba7285192c4d210afcc5b889f2f33d1a43ede01a Mon Sep 17 00:00:00 2001 From: Asher Date: Fri, 9 Aug 2019 18:50:05 -0500 Subject: [PATCH] Update VS Code to 1.37.0 --- .travis.yml | 6 +- README.md | 18 +- scripts/build-json.js | 58 ++ scripts/merge.js | 23 - scripts/tasks.bash | 10 +- scripts/vscode.patch | 1663 ++++++-------------------------- src/api.ts | 45 +- src/channel.ts | 14 +- src/cli.ts | 41 +- src/client.ts | 25 +- src/connection.ts | 8 +- src/insights.ts | 3 +- src/ipc.ts | 1 - src/{tar.ts => marketplace.ts} | 20 +- src/nls.ts | 3 +- src/protocol.ts | 3 +- src/server.ts | 91 +- src/telemetry.ts | 49 + src/update.ts | 25 +- src/upload.ts | 113 ++- src/util.ts | 16 +- 21 files changed, 645 insertions(+), 1590 deletions(-) create mode 100644 scripts/build-json.js delete mode 100644 scripts/merge.js rename src/{tar.ts => marketplace.ts} (91%) create mode 100644 src/telemetry.ts diff --git a/.travis.yml b/.travis.yml index c90680c6..e9276630 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,14 +8,14 @@ matrix: - os: linux dist: trusty env: - - VSCODE_VERSION="1.36.1" MAJOR_VERSION="2" VERSION="$MAJOR_VERSION.$TRAVIS_BUILD_NUMBER" TARGET="linux" + - VSCODE_VERSION="1.37.0" MAJOR_VERSION="2" VERSION="$MAJOR_VERSION.$TRAVIS_BUILD_NUMBER" TARGET="linux" - os: linux dist: trusty env: - - VSCODE_VERSION="1.36.1" MAJOR_VERSION="2" VERSION="$MAJOR_VERSION.$TRAVIS_BUILD_NUMBER" TARGET="alpine" + - VSCODE_VERSION="1.37.0" MAJOR_VERSION="2" VERSION="$MAJOR_VERSION.$TRAVIS_BUILD_NUMBER" TARGET="alpine" - os: osx env: - - VSCODE_VERSION="1.36.1" MAJOR_VERSION="2" VERSION="$MAJOR_VERSION.$TRAVIS_BUILD_NUMBER" + - VSCODE_VERSION="1.37.0" MAJOR_VERSION="2" VERSION="$MAJOR_VERSION.$TRAVIS_BUILD_NUMBER" before_install: - if [[ "$TRAVIS_BRANCH" == "master" ]]; then export MINIFY="true"; fi script: diff --git a/README.md b/README.md index 2824d2b0..b4f03145 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ data collected to improve code-server. ```shell git clone https://github.com/microsoft/vscode cd vscode -git checkout 1.36.1 +git checkout 1.37.0 git clone https://github.com/cdr/code-server src/vs/server cd src/vs/server yarn patch:apply @@ -109,23 +109,19 @@ directory. Our changes include: - Add a `code-server` schema. -- Make the extension sidebar work in the browser. Mostly involves removing - Node-specific code for the `extensions` channel client and adding a - `gallery` channel. - Allow multiple extension directories (both user and built-in). -- Rewrite assets used in the CSS (like icons) or as images to use the base URL. -- Change the loader to use the base URL. -- Change the web socket to use the base URL and TLS if necessary. -- Set the favicon using a relative path. -- Modify the file service to support writing from an asynchronous stream (for - uploading files). +- Rewrite assets requested by the browser to use the base URL. +- Modify the loader to use the base URL. +- Modify the web socket to use the base URL and TLS if necessary. +- Send client-side telemetry through the server. - Add a file prefix to ignore for temporary files created during upload. - Insert our upload service for use in editor windows and explorer. - Modify the log level to get its initial setting from the server. -- Get telemetry working by adding a channel for it. - Change a regular expression used for mnemonics so it works on Firefox. - Make it possible for us to load code on the client. - Modify the build process to include our code. +- Fix a CSP issue within a webview. +- Fix an issue displaying extension contributions. ## License [MIT](LICENSE) diff --git a/scripts/build-json.js b/scripts/build-json.js new file mode 100644 index 00000000..188d4dae --- /dev/null +++ b/scripts/build-json.js @@ -0,0 +1,58 @@ +// This builds the package and product JSON files for the final build. +const crypto = require("crypto"); +const fs = require("fs"); +const path = require("path"); +const rootPath = path.resolve(__dirname, ".."); +const sourcePath = process.argv[2]; +const buildPath = process.argv[3]; +const vscodeVersion = process.argv[4]; +const codeServerVersion = process.argv[5]; +const util = require(path.join(sourcePath, "build/lib/util")); + +function computeChecksum(filename) { + return crypto.createHash("md5").update(fs.readFileSync(filename)) + .digest("base64").replace(/=+$/, ""); +} + +const computeChecksums = (filenames) => { + const result = {}; + filenames.forEach(function (filename) { + result[filename] = computeChecksum(path.join(buildPath, "out", filename)); + }); + return result; +}; + +const mergeAndWrite = (name, json = {}) => { + const aJson = JSON.parse(fs.readFileSync(path.join(sourcePath, `${name}.json`))); + const bJson = JSON.parse(fs.readFileSync(path.join(rootPath, "scripts", `${name}.json`))); + + delete aJson.scripts; + delete aJson.dependencies; + delete aJson.devDependencies; + delete aJson.optionalDependencies; + + fs.writeFileSync(path.join(buildPath, `${name}.json`), JSON.stringify({ + ...aJson, + ...bJson, + ...json, + }, null, 2)); +}; + + +const writeProduct = () => { + const checksums = computeChecksums([ + "vs/workbench/workbench.web.api.js", + "vs/workbench/workbench.web.api.css", + "vs/code/browser/workbench/workbench.html", + "vs/code/browser/workbench/workbench.js", + "vs/server/src/cli.js", + "vs/server/src/uriTransformer.js", + "vs/server/src/login/index.html" + ]); + const date = new Date().toISOString(); + const commit = util.getVersion(rootPath); + mergeAndWrite("product", { commit, date, checksums }); + mergeAndWrite("package", { codeServerVersion: `${codeServerVersion}-vsc${vscodeVersion}` }); +}; + +writeProduct(); diff --git a/scripts/merge.js b/scripts/merge.js deleted file mode 100644 index 045dba64..00000000 --- a/scripts/merge.js +++ /dev/null @@ -1,23 +0,0 @@ -// This is used to merge JSON files (package.json and product.json) and delete a -// few entries we don't want. It's extremely simple, expects very specific -// input, and doesn't have any error handling. -const fs = require("fs"); - -const a = process.argv[2]; -const b = process.argv[3]; -const out = process.argv[4]; -const json = JSON.parse(process.argv[5] || "{}"); - -const aJson = JSON.parse(fs.readFileSync(a)); -const bJson = JSON.parse(fs.readFileSync(b)); - -delete aJson.scripts; -delete aJson.dependencies; -delete aJson.devDependencies; -delete aJson.optionalDependencies; - -fs.writeFileSync(out, JSON.stringify({ - ...aJson, - ...bJson, - ...json, -}, null, 2)); diff --git a/scripts/tasks.bash b/scripts/tasks.bash index 9b63b5e2..8a5a2039 100755 --- a/scripts/tasks.bash +++ b/scripts/tasks.bash @@ -56,9 +56,9 @@ function prepend-loader() { # Copy code-server into VS Code then build it. function build-code-server() { copy-server + yarn gulp compile-build --max-old-space-size=32384 + local min="" - export BUILD_SOURCEVERSION - BUILD_SOURCEVERSION=$(node -p "require('${sourcePath}/build/lib/git.js').getVersion('${rootPath}')") if [[ -n "${minify}" ]] ; then min="-min" yarn gulp minify-vscode --max-old-space-size=32384 @@ -74,11 +74,9 @@ function build-code-server() { cd "${buildPath}" && yarn --production --force --build-from-source rm "${buildPath}/"{package.json,yarn.lock,.yarnrc} - local packageJson="{\"codeServerVersion\": \"${codeServerVersion}-vsc${vscodeVersion}\"}" cp -r "${sourcePath}/.build/extensions" "${buildPath}" - node "${rootPath}/scripts/merge.js" "${sourcePath}/package.json" "${rootPath}/scripts/package.json" "${buildPath}/package.json" "${packageJson}" - node "${rootPath}/scripts/merge.js" "${sourcePath}/.build/product.json" "${rootPath}/scripts/product.json" "${buildPath}/product.json" cp -r "${sourcePath}/out-vscode${min}" "${buildPath}/out" + node "${rootPath}/scripts/build-json.js" "${sourcePath}" "${buildPath}" "${vscodeVersion}" "${codeServerVersion}" # Only keep production dependencies for the server. cp "${rootPath}/"{package.json,yarn.lock} "${buildPath}/out/vs/server" @@ -143,7 +141,7 @@ function build-task() { log "Pre-built VS Code ${vscodeVersion} has no built extensions" "error" exit 1 fi - yarn gulp extensions-build-package --max-old-space-size=32384 + yarn gulp compile-extensions-build --max-old-space-size=32384 fi build-code-server } diff --git a/scripts/vscode.patch b/scripts/vscode.patch index cf44076b..a994b16e 100644 --- a/scripts/vscode.patch +++ b/scripts/vscode.patch @@ -1,40 +1,20 @@ -diff --git a/build/gulpfile.compile.js b/build/gulpfile.compile.js -index 0dd2e5abf1..fc6875f3c2 100644 ---- a/build/gulpfile.compile.js -+++ b/build/gulpfile.compile.js -@@ -12,6 +12,7 @@ const { compileExtensionsBuildTask } = require('./gulpfile.extensions'); - - // Full compile, including nls and inline sources in sourcemaps, for build - const compileClientBuildTask = task.define('compile-client-build', task.series(util.rimraf('out-build'), compilation.compileTask('src', 'out-build', true))); -+exports.compileClientBuildTask = compileClientBuildTask; - - // All Build - const compileBuildTask = task.define('compile-build', task.parallel(compileClientBuildTask, compileExtensionsBuildTask)); diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js -index 84a6be26e8..d4c3ebc7bd 100644 +index 99bd930a91..319c4bd3c3 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js -@@ -34,7 +34,8 @@ const deps = require('./dependencies'); - const getElectronVersion = require('./lib/electron').getElectronVersion; - const createAsar = require('./lib/asar').createAsar; - const minimist = require('minimist'); --const { compileBuildTask } = require('./gulpfile.compile'); -+const { /*compileBuildTask, */compileClientBuildTask } = require('./gulpfile.compile'); -+const { compileExtensionsBuildTask } = require('./gulpfile.extensions'); - - const productionDependencies = deps.getProductionDependencies(path.dirname(__dirname)); - // @ts-ignore -@@ -47,23 +48,28 @@ const nodeModules = ['electron', 'original-fs'] +@@ -47,24 +47,31 @@ const nodeModules = ['electron', 'original-fs'] // Build const vscodeEntryPoints = _.flatten([ - buildfile.entrypoint('vs/workbench/workbench.main'), ++ // buildfile.entrypoint('vs/workbench/workbench.main'), + buildfile.entrypoint('vs/workbench/workbench.web.api'), + buildfile.entrypoint('vs/server/src/cli'), + buildfile.entrypoint('vs/workbench/services/keybinding/browser/keyboardLayouts/layout.contribution.linux'), + buildfile.entrypoint('vs/workbench/services/keybinding/browser/keyboardLayouts/layout.contribution.win'), + buildfile.entrypoint('vs/workbench/services/keybinding/browser/keyboardLayouts/layout.contribution.darwin'), buildfile.base, + buildfile.serviceWorker, - buildfile.workbench, - buildfile.code + buildfile.workbenchWeb, @@ -45,31 +25,33 @@ index 84a6be26e8..d4c3ebc7bd 100644 - 'out-build/main.js', - 'out-build/cli.js', - 'out-build/driver.js', -+ 'out-build/vs/server/main.js', -+ 'out-build/vs/server/src/uriTransformer.js', ++ // 'out-build/main.js', + // 'out-build/cli.js', + // 'out-build/driver.js', ++ 'out-build/vs/server/main.js', ++ 'out-build/vs/server/src/uriTransformer.js', 'out-build/bootstrap.js', 'out-build/bootstrap-fork.js', 'out-build/bootstrap-amd.js', 'out-build/bootstrap-window.js', 'out-build/paths.js', -- 'out-build/vs/**/*.{svg,png,cur,html}', +- 'out-build/vs/**/*.{svg,png,html}', - '!out-build/vs/code/browser/**/*.html', -+ 'out-build/vs/**/*.{svg,png,cur,html,ico}', ++ 'out-build/vs/**/*.{svg,png,html,ico}', + // '!out-build/vs/code/browser/**/*.html', 'out-build/vs/base/common/performance.js', 'out-build/vs/base/node/languagePacks.js', 'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh,ps.sh}', -@@ -78,10 +84,11 @@ const vscodeResources = [ +@@ -79,10 +86,12 @@ const vscodeResources = [ 'out-build/vs/workbench/contrib/welcome/walkThrough/**/*.md', - 'out-build/vs/workbench/services/files/**/*.exe', - 'out-build/vs/workbench/services/files/**/*.md', + 'out-build/vs/platform/files/**/*.exe', + 'out-build/vs/platform/files/**/*.md', - 'out-build/vs/code/electron-browser/workbench/**', - 'out-build/vs/code/electron-browser/sharedProcess/sharedProcess.js', - 'out-build/vs/code/electron-browser/issue/issueReporter.js', - 'out-build/vs/code/electron-browser/processExplorer/processExplorer.js', + 'out-build/vs/code/browser/workbench/**', ++ // 'out-build/vs/code/electron-browser/workbench/**', + // 'out-build/vs/code/electron-browser/sharedProcess/sharedProcess.js', + // 'out-build/vs/code/electron-browser/issue/issueReporter.js', + // 'out-build/vs/code/electron-browser/processExplorer/processExplorer.js', @@ -77,78 +59,33 @@ index 84a6be26e8..d4c3ebc7bd 100644 '!**/test/**' ]; -@@ -94,7 +101,7 @@ const BUNDLED_FILE_HEADER = [ - const optimizeVSCodeTask = task.define('optimize-vscode', task.series( - task.parallel( - util.rimraf('out-vscode'), -- compileBuildTask -+ compileClientBuildTask // compileBuildTask - ), - common.optimizeTask({ - src: 'out-build', -@@ -104,7 +111,8 @@ const optimizeVSCodeTask = task.define('optimize-vscode', task.series( - header: BUNDLED_FILE_HEADER, - out: 'out-vscode', - bundleInfo: undefined -- }) -+ }), -+ () => writeProduct() - )); - - -@@ -124,9 +132,36 @@ const minifyVSCodeTask = task.define('minify-vscode', task.series( - util.rimraf('out-vscode-min'), - optimizeIndexJSTask - ), -- common.minifyTask('out-vscode', `${sourceMappingURLBase}/core`) -+ common.minifyTask('out-vscode', `${sourceMappingURLBase}/core`), -+ () => writeProduct('out-vscode-min') - )); - -+function packageExtensionsTask() { -+ return () => ext.packageExtensionsStream().pipe(vfs.dest(path.join(root, '.build'))); -+} -+gulp.task(task.define('extensions-build-package', task.series( -+ compileExtensionsBuildTask, -+ packageExtensionsTask() -+))); -+gulp.task(optimizeVSCodeTask); -+gulp.task(minifyVSCodeTask); -+function writeProduct(sourceFolderName) { -+ const checksums = sourceFolderName && computeChecksums(sourceFolderName, [ -+ 'vs/workbench/workbench.web.api.js', -+ 'vs/workbench/workbench.web.api.css', -+ 'vs/code/browser/workbench/workbench.html', -+ 'vs/code/browser/workbench/workbench.js', -+ 'vs/server/src/cli.js', -+ 'vs/server/src/uriTransformer.js', -+ 'vs/server/src/login/index.html' -+ ]); -+ const date = new Date().toISOString(); -+ const productJsonUpdate = { commit, date, checksums }; -+ return gulp.src(['product.json'], { base: '.' }) -+ .pipe(json(productJsonUpdate)) -+ .pipe(vfs.dest(path.join(root, '.build'))); -+} -+ - // Package - - // @ts-ignore JSON checking: darwinCredits is optional -diff --git a/src/typings/require.d.ts b/src/typings/require.d.ts -index 618861a5be..9d4fdea14e 100644 ---- a/src/typings/require.d.ts -+++ b/src/typings/require.d.ts -@@ -46,5 +46,7 @@ interface NodeRequire { - config(data: any): any; - onError: Function; - __$__nodeRequire(moduleName: string): T; -- getStats(): ReadonlyArray -+ getStats(): ReadonlyArray; -+ withBase(path: string ): string; -+ withBase(resource: { path: string }): { toString: (skipEncoding?: boolean) => string }; +diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts +index fa12f62900..1dbaac1640 100644 +--- a/src/vs/base/browser/dom.ts ++++ b/src/vs/base/browser/dom.ts +@@ -1187,6 +1187,7 @@ export function animate(fn: () => void): IDisposable { + + + ++const basePath = window.location.pathname.replace(/\/+$/, ''); + const _location = URI.parse(window.location.href); + + export function asDomUri(uri: URI): URI { +@@ -1197,10 +1198,10 @@ export function asDomUri(uri: URI): URI { + //todo@joh remove this once we have sw in electron going + return uri; + } +- if (Schemas.vscodeRemote === uri.scheme) { ++ if (Schemas.codeServer === uri.scheme) { + // rewrite vscode-remote-uris to uris of the window location + // so that they can be intercepted by the service worker +- return _location.with({ path: '/vscode-resources/fetch', query: `u=${JSON.stringify(uri)}` }); ++ return _location.with({ path: `${basePath}/vscode-resources/${uri.fsPath}` }); + } + return uri; } diff --git a/src/vs/base/browser/ui/menu/menu.ts b/src/vs/base/browser/ui/menu/menu.ts -index 7913bb42fd..80d5970970 100644 +index c2b60a5dc9..3f40fa0bdf 100644 --- a/src/vs/base/browser/ui/menu/menu.ts +++ b/src/vs/base/browser/ui/menu/menu.ts @@ -22,7 +22,7 @@ import { isLinux, isMacintosh } from 'vs/base/common/platform'; @@ -160,63 +97,35 @@ index 7913bb42fd..80d5970970 100644 } catch (err) { return new RegExp('\uFFFF'); // never match please } -@@ -799,7 +799,7 @@ export function cleanMnemonic(label: string): string { +@@ -802,7 +802,7 @@ export function cleanMnemonic(label: string): string { return label; } - const mnemonicInText = matches[0].charAt(0) === '&'; -+ const mnemonicInText = matches[3]; // matches[0].charAt(0) === '&'; ++ const mnemonicInText = matches[3]; - return label.replace(regex, mnemonicInText ? '$2' : '').trim(); --} -\ No newline at end of file + return label.replace(regex, mnemonicInText ? '$2$3' : '').trim(); -+} -diff --git a/src/vs/base/common/buffer.ts b/src/vs/base/common/buffer.ts -index 7b4e9cc8d6..7722cb12c6 100644 ---- a/src/vs/base/common/buffer.ts -+++ b/src/vs/base/common/buffer.ts -@@ -138,7 +138,7 @@ export interface VSBufferReadable { - * Read data from the underlying source. Will return - * null to indicate that no more data can be read. - */ -- read(): VSBuffer | null; -+ read(): VSBuffer | null | Promise; } - - /** -@@ -185,11 +185,11 @@ export interface VSBufferReadableStream { - /** - * Helper to fully read a VSBuffer readable into a single buffer. - */ --export function readableToBuffer(readable: VSBufferReadable): VSBuffer { -+export async function readableToBuffer(readable: VSBufferReadable): Promise { - const chunks: VSBuffer[] = []; - - let chunk: VSBuffer | null; -- while (chunk = readable.read()) { -+ while (chunk = await readable.read()) { - chunks.push(chunk); - } - diff --git a/src/vs/base/common/network.ts b/src/vs/base/common/network.ts -index a7466e641a..6d91e66ad3 100644 +index 46d2933a05..7e8ca77342 100644 --- a/src/vs/base/common/network.ts +++ b/src/vs/base/common/network.ts -@@ -46,4 +46,6 @@ export namespace Schemas { +@@ -46,6 +46,7 @@ export namespace Schemas { export const command: string = 'command'; export const vscodeRemote: string = 'vscode-remote'; -+ + export const codeServer: string = 'code-server'; + + export const userData: string = 'vscode-userdata'; } diff --git a/src/vs/base/common/platform.ts b/src/vs/base/common/platform.ts -index 4cba839fe5..b216c43bbc 100644 +index d7371552d3..d2ab92983e 100644 --- a/src/vs/base/common/platform.ts +++ b/src/vs/base/common/platform.ts -@@ -53,8 +53,18 @@ if (typeof navigator === 'object' && !isElectronRenderer) { - _isMacintosh = userAgent.indexOf('Macintosh') >= 0; - _isLinux = userAgent.indexOf('Linux') >= 0; +@@ -54,8 +54,18 @@ if (typeof navigator === 'object' && !isElectronRenderer) { + _isMacintosh = _userAgent.indexOf('Macintosh') >= 0; + _isLinux = _userAgent.indexOf('Linux') >= 0; _isWeb = true; - _locale = navigator.language; - _language = _locale; @@ -236,31 +145,39 @@ index 4cba839fe5..b216c43bbc 100644 _isWindows = (process.platform === 'win32'); _isMacintosh = (process.platform === 'darwin'); diff --git a/src/vs/code/browser/workbench/workbench.html b/src/vs/code/browser/workbench/workbench.html -index ff62e0a65a..924b65fa7a 100644 +index 5b06636edb..60b508079a 100644 --- a/src/vs/code/browser/workbench/workbench.html +++ b/src/vs/code/browser/workbench/workbench.html -@@ -4,6 +4,8 @@ +@@ -4,7 +4,7 @@ -+ -+ - - +- ++ -@@ -20,6 +22,7 @@ + + +@@ -19,13 +19,14 @@ - - + + + - + + + + +- ++ + + + diff --git a/src/vs/code/browser/workbench/workbench.js b/src/vs/code/browser/workbench/workbench.js -index 34f321f90d..b1bd6a4ac9 100644 +index 65fae7c82d..c9744007c9 100644 --- a/src/vs/code/browser/workbench/workbench.js +++ b/src/vs/code/browser/workbench/workbench.js -@@ -7,14 +7,19 @@ +@@ -7,15 +7,20 @@ (function () { @@ -278,213 +195,61 @@ index 34f321f90d..b1bd6a4ac9 100644 - 'xterm': `${window.location.origin}/node_modules/xterm/lib/xterm.js`, - 'xterm-addon-search': `${window.location.origin}/node_modules/xterm-addon-search/lib/xterm-addon-search.js`, - 'xterm-addon-web-links': `${window.location.origin}/node_modules/xterm-addon-web-links/lib/xterm-addon-web-links.js`, +- 'semver-umd': `${window.location.origin}/node_modules/semver-umd/lib/semver-umd.js`, + 'vscode-textmate': `${base}/node_modules/vscode-textmate/release/main`, + 'onigasm-umd': `${base}/node_modules/onigasm-umd/release/main`, + 'xterm': `${base}/node_modules/xterm/lib/xterm.js`, + 'xterm-addon-search': `${base}/node_modules/xterm-addon-search/lib/xterm-addon-search.js`, + 'xterm-addon-web-links': `${base}/node_modules/xterm-addon-web-links/lib/xterm-addon-web-links.js`, ++ 'semver-umd': `${base}/node_modules/semver-umd/lib/semver-umd.js`, } }); -diff --git a/src/vs/loader.js b/src/vs/loader.js -index 40b6d2aa32..f64b7e70d8 100644 ---- a/src/vs/loader.js -+++ b/src/vs/loader.js -@@ -497,6 +497,29 @@ var AMDLoader; - } - return this._addUrlArgsIfNecessaryToUrl(result); - }; -+ /** -+ * Transform a code-server:// URI, file:// URI, or plain path to use -+ * the site base. -+ */ -+ Configuration.prototype.requireWithBase = function (resource) { -+ if (typeof this.options.basePath === "undefined" || typeof this.options.baseAuthority === "undefined" || typeof this.options.baseScheme === "undefined") { -+ return resource; -+ } -+ if (typeof resource === "string") { -+ const base = `${this.options.baseScheme}://${this.options.baseAuthority}${this.options.basePath}`; -+ return resource.indexOf("/") !== 0 -+ ? resource.replace(/^(code-server|file):\/\/[^/]*/, `${base}/resources`) -+ : `${base}${resource}`; -+ } -+ if (resource.scheme !== "code-server" && resource.scheme !== "file") { -+ return resource; -+ } -+ return resource.with({ -+ authority: this.options.baseAuthority, -+ scheme: this.options.baseScheme, -+ path: `${this.options.basePath}/resources${resource.path}`, -+ }); -+ }; - /** - * Flag to indicate if current execution is as part of a build. - */ -@@ -1427,6 +1450,9 @@ var AMDLoader; - result.getStats = function () { - return _this.getLoaderEvents(); - }; -+ result.withBase = function (resource) { -+ return _this._config.requireWithBase(resource); -+ }; - result.__$__nodeRequire = AMDLoader.global.nodeRequire; - return result; - }; -diff --git a/src/vs/platform/actions/browser/menuEntryActionViewItem.ts b/src/vs/platform/actions/browser/menuEntryActionViewItem.ts -index 2dae143385..3fa8ac96d1 100644 ---- a/src/vs/platform/actions/browser/menuEntryActionViewItem.ts -+++ b/src/vs/platform/actions/browser/menuEntryActionViewItem.ts -@@ -244,8 +244,8 @@ export class MenuEntryActionViewItem extends ActionViewItem { - iconClass = MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!; - } else { - iconClass = ids.nextId(); -- createCSSRule(`.icon.${iconClass}`, `background-image: url("${(item.iconLocation.light || item.iconLocation.dark).toString()}")`); -- createCSSRule(`.vs-dark .icon.${iconClass}, .hc-black .icon.${iconClass}`, `background-image: url("${item.iconLocation.dark.toString()}")`); -+ createCSSRule(`.icon.${iconClass}`, `background-image: url("${require.withBase(item.iconLocation.light || item.iconLocation.dark).toString()}")`); -+ createCSSRule(`.vs-dark .icon.${iconClass}, .hc-black .icon.${iconClass}`, `background-image: url("${require.withBase(item.iconLocation.dark).toString()}")`); - MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass); - } - diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts -index 443e430fcd..fdd9900598 100644 +index a6c9eb9d11..3f8995b727 100644 --- a/src/vs/platform/environment/common/environment.ts +++ b/src/vs/platform/environment/common/environment.ts -@@ -156,4 +156,7 @@ export interface IEnvironmentService { +@@ -81,6 +81,8 @@ export interface ParsedArgs { - webviewEndpoint?: string; - readonly webviewResourceRoot: string; -+ + // Web flags + 'web-user-data-dir'?: string; ++ 'extra-extensions-dir'?: string | string[]; ++ 'extra-builtin-extensions-dir'?: string | string[]; + } + + export const IEnvironmentService = createDecorator('environmentService'); +@@ -173,4 +175,6 @@ export interface IEnvironmentService { + readonly webviewCspSource: string; + + readonly galleryMachineIdResource?: URI; + extraExtensionPaths: string[]; + extraBuiltinExtensionPaths: string[]; } diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts -index 55c3d8302a..b8568fa785 100644 +index 9373b22383..33ebcfc081 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts -@@ -276,6 +276,16 @@ export class EnvironmentService implements IEnvironmentService { - return 'vscode-resource:'; - } +@@ -277,6 +277,15 @@ export class EnvironmentService implements IEnvironmentService { -+ @memoize -+ get extraExtensionPaths(): string[] { -+ return (this._args['extra-extensions-dir'] || []).map((p: string) => parsePathArg(p, process)); + readonly webviewResourceRoot = 'vscode-resource:{{resource}}'; + readonly webviewCspSource = 'vscode-resource:'; ++ @memoize get extraExtensionPaths(): string[] { ++ return this.arrayify(this._args['extra-extensions-dir']).map((p) => parsePathArg(p, process)); + } -+ -+ @memoize -+ get extraBuiltinExtensionPaths(): string[] { -+ return (this._args['extra-builtin-extensions-dir'] || []).map((p: string) => parsePathArg(p, process)); ++ @memoize get extraBuiltinExtensionPaths(): string[] { ++ return this.arrayify(this._args['extra-builtin-extensions-dir']).map((p) => parsePathArg(p, process)); + } -+ ++ private arrayify(arg: T | T[] = []): T[] { ++ return (Array.isArray(arg) ? arg : [arg]); ++ } + constructor(private _args: ParsedArgs, private _execPath: string) { if (!process.env['VSCODE_LOGS']) { - const key = toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, ''); -diff --git a/src/vs/platform/extensionManagement/node/extensionGalleryIpc.ts b/src/vs/platform/extensionManagement/node/extensionGalleryIpc.ts -new file mode 100644 -index 0000000000..ef1db87989 ---- /dev/null -+++ b/src/vs/platform/extensionManagement/node/extensionGalleryIpc.ts -@@ -0,0 +1,96 @@ -+import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; -+import { IGalleryExtension, IReportedExtension, IExtensionGalleryService, IQueryOptions, InstallOperation, StatisticType, IGalleryExtensionVersion, ITranslation } from 'vs/platform/extensionManagement/common/extensionManagement'; -+import { Event } from 'vs/base/common/event'; -+import { IExtensionManifest, IExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; -+import { IPager } from 'vs/base/common/paging'; -+import { CancellationToken } from 'vs/base/common/cancellation'; -+import { IProductService } from 'vs/platform/product/common/product'; -+ -+export class ExtensionGalleryChannel implements IServerChannel { -+ -+ constructor(private service: IExtensionGalleryService) {} -+ -+ listen(_: unknown, _event: string): Event { -+ throw new Error('Invalid listen'); -+ } -+ -+ call(_: unknown, command: string, args?: any, cancellationToken?: CancellationToken): Promise { -+ switch (command) { -+ case 'query': return args.length > 0 ? this.service.query(args[0], cancellationToken!) : this.service.query(cancellationToken!); -+ case 'download': return this.service.download(args[0], args[1]); -+ case 'reportStatistic': return this.service.reportStatistic(args[0], args[1], args[2], args[3]); -+ case 'getReadme': return this.service.getReadme(args[0], cancellationToken!); -+ case 'getManifest': return this.service.getManifest(args[0], cancellationToken!); -+ case 'getChangelog': return this.service.getChangelog(args[0], cancellationToken!); -+ case 'getCoreTranslation': return this.service.getCoreTranslation(args[0], args[1]); -+ case 'getAllVersions': return this.service.getAllVersions(args[0], args[1]); -+ case 'getExtensionsReport': return this.service.getExtensionsReport(); -+ case 'getCompatibleExtension': return this.service.getCompatibleExtension(args[0], args[1]); -+ } -+ -+ throw new Error(`Invalid call: ${command}`); -+ } -+} -+ -+export class ExtensionGalleryChannelClient implements IExtensionGalleryService { -+ -+ _serviceBrand: any; -+ -+ private extensionsGalleryUrl: string | undefined; -+ -+ constructor( -+ private readonly channel: IChannel, -+ productService: IProductService, -+ ) { -+ const config = productService.extensionsGallery; -+ this.extensionsGalleryUrl = config && config.serviceUrl; -+ } -+ -+ isEnabled(): boolean { -+ return !!this.extensionsGalleryUrl; -+ } -+ -+ query(token: CancellationToken): Promise>; -+ query(options: IQueryOptions, token: CancellationToken): Promise>; -+ query(options: IQueryOptions | CancellationToken, token?: CancellationToken): Promise> { -+ return this.channel.call('query', CancellationToken.isCancellationToken(options) ? [] : [ options ], token); -+ } -+ -+ download(extension: IGalleryExtension, operation: InstallOperation): Promise { -+ return this.channel.call('download', [ extension, operation ]); -+ } -+ -+ reportStatistic(publisher: string, name: string, version: string, type: StatisticType): Promise { -+ return this.channel.call('reportStatistic', [ publisher, name, version, type ]); -+ } -+ -+ getReadme(extension: IGalleryExtension, token: CancellationToken): Promise { -+ return this.channel.call('getReadme', [ extension ], token); -+ } -+ -+ getManifest(extension: IGalleryExtension, token: CancellationToken): Promise { -+ return this.channel.call('getManifest', [ extension ], token); -+ } -+ -+ getChangelog(extension: IGalleryExtension, token: CancellationToken): Promise { -+ return this.channel.call('getChangelog', [ extension ], token); -+ } -+ -+ getCoreTranslation(extension: IGalleryExtension, languageId: string): Promise { -+ return this.channel.call('getCoreTranslation', [ extension, languageId ]); -+ } -+ -+ getAllVersions(extension: IGalleryExtension, compatible: boolean): Promise { -+ return this.channel.call('getAllVersions', [ extension, compatible ]); -+ } -+ -+ getExtensionsReport(): Promise { -+ return this.channel.call('getExtensionsReport'); -+ } -+ -+ getCompatibleExtension(extension: IGalleryExtension): Promise; -+ getCompatibleExtension(id: IExtensionIdentifier, version?: string): Promise; -+ getCompatibleExtension(id: IExtensionIdentifier | IGalleryExtension, version?: string): Promise { -+ return this.channel.call('getCompatibleExtension', [ id, version ]); -+ } -+} diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts -index e09049c5b9..7af2c20efd 100644 +index 70cd46c824..33d661644b 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts -@@ -724,11 +724,15 @@ export class ExtensionManagementService extends Disposable implements IExtension +@@ -725,11 +725,15 @@ export class ExtensionManagementService extends Disposable implements IExtension private scanSystemExtensions(): Promise { this.logService.trace('Started scanning system extensions'); @@ -505,7 +270,7 @@ index e09049c5b9..7af2c20efd 100644 if (this.environmentService.isBuilt) { return systemExtensionsPromise; } -@@ -750,9 +754,16 @@ export class ExtensionManagementService extends Disposable implements IExtension +@@ -751,9 +755,16 @@ export class ExtensionManagementService extends Disposable implements IExtension .then(([systemExtensions, devSystemExtensions]) => [...systemExtensions, ...devSystemExtensions]); } @@ -523,7 +288,7 @@ index e09049c5b9..7af2c20efd 100644 .then(([uninstalled, extensions]) => { extensions = extensions.filter(e => !uninstalled[new ExtensionIdentifierWithVersion(e.identifier, e.manifest.version).key()]); if (excludeOutdated) { -@@ -805,7 +816,7 @@ export class ExtensionManagementService extends Disposable implements IExtension +@@ -806,7 +817,7 @@ export class ExtensionManagementService extends Disposable implements IExtension private async removeUninstalledExtensions(): Promise { const uninstalled = await this.getUninstalledExtensions(); @@ -532,7 +297,7 @@ index e09049c5b9..7af2c20efd 100644 const installed: Set = new Set(); for (const e of extensions) { if (!uninstalled[new ExtensionIdentifierWithVersion(e.identifier, e.manifest.version).key()]) { -@@ -824,7 +835,7 @@ export class ExtensionManagementService extends Disposable implements IExtension +@@ -825,7 +836,7 @@ export class ExtensionManagementService extends Disposable implements IExtension } private removeOutdatedExtensions(): Promise { @@ -542,36 +307,31 @@ index e09049c5b9..7af2c20efd 100644 const toRemove: ILocalExtension[] = []; diff --git a/src/vs/platform/localizations/electron-browser/localizationsService.ts b/src/vs/platform/localizations/electron-browser/localizationsService.ts -index 353161166e..7d64fe93c7 100644 +index 353161166e..cff8e2750e 100644 --- a/src/vs/platform/localizations/electron-browser/localizationsService.ts +++ b/src/vs/platform/localizations/electron-browser/localizationsService.ts -@@ -6,8 +6,9 @@ +@@ -6,7 +6,7 @@ import { IChannel } from 'vs/base/parts/ipc/common/ipc'; import { Event } from 'vs/base/common/event'; import { ILocalizationsService, LanguageType } from 'vs/platform/localizations/common/localizations'; -import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; -+// import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; - import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; +import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; + import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; export class LocalizationsService implements ILocalizationsService { - -@@ -15,8 +16,11 @@ export class LocalizationsService implements ILocalizationsService { +@@ -15,8 +15,8 @@ export class LocalizationsService implements ILocalizationsService { private channel: IChannel; - constructor(@ISharedProcessService sharedProcessService: ISharedProcessService) { - this.channel = sharedProcessService.getChannel('localizations'); -+ constructor( -+ // @ISharedProcessService sharedProcessService: ISharedProcessService -+ @IRemoteAgentService remoteAgentService: IRemoteAgentService, -+ ) { ++ constructor(@IRemoteAgentService remoteAgentService: IRemoteAgentService) { + this.channel = remoteAgentService.getConnection()!.getChannel('localizations'); } get onDidLanguagesChange(): Event { return this.channel.listen('onDidLanguagesChange'); } diff --git a/src/vs/platform/log/common/logIpc.ts b/src/vs/platform/log/common/logIpc.ts -index 9f68b645b6..f0cae7111d 100644 +index 9f68b645b6..54f9e26c88 100644 --- a/src/vs/platform/log/common/logIpc.ts +++ b/src/vs/platform/log/common/logIpc.ts @@ -26,6 +26,7 @@ export class LogLevelSetterChannel implements IServerChannel { @@ -582,19 +342,18 @@ index 9f68b645b6..f0cae7111d 100644 } throw new Error(`Call not found: ${command}`); -@@ -40,6 +41,10 @@ export class LogLevelSetterChannelClient { - return this.channel.listen('onDidChangeLogLevel'); +@@ -43,6 +44,9 @@ export class LogLevelSetterChannelClient { + setLevel(level: LogLevel): void { + this.channel.call('setLevel', level); } - + getLevel(): Promise { + return this.channel.call('getLevel'); + } -+ - setLevel(level: LogLevel): void { - this.channel.call('setLevel', level); - } + } + + export class FollowerLogService extends DelegatedLogService implements ILogService { diff --git a/src/vs/platform/product/browser/productService.ts b/src/vs/platform/product/browser/productService.ts -index 084144d009..d91176c9cd 100644 +index fbdf03fd3e..d498d4d192 100644 --- a/src/vs/platform/product/browser/productService.ts +++ b/src/vs/platform/product/browser/productService.ts @@ -17,7 +17,7 @@ export class ProductService implements IProductService { @@ -604,7 +363,7 @@ index 084144d009..d91176c9cd 100644 - get version(): string { return '1.35.0'; } + get version(): string { return this.productConfiguration ? (this.productConfiguration as any).version : 'development'; } - get commit(): string | undefined { return undefined; } + get commit(): string | undefined { return this.productConfiguration ? this.productConfiguration.commit : undefined; } diff --git a/src/vs/platform/product/node/package.ts b/src/vs/platform/product/node/package.ts index d39c5877d6..c189d6f19f 100644 @@ -618,157 +377,96 @@ index d39c5877d6..c189d6f19f 100644 } const rootPath = path.dirname(getPathFromAmdModule(require, '')); -diff --git a/src/vs/platform/remote/browser/browserWebSocketFactory.ts b/src/vs/platform/remote/browser/browserWebSocketFactory.ts -index 6d9ecbcf5a..a3eb980965 100644 ---- a/src/vs/platform/remote/browser/browserWebSocketFactory.ts -+++ b/src/vs/platform/remote/browser/browserWebSocketFactory.ts -@@ -79,7 +79,7 @@ class BrowserSocket implements ISocket { - export const browserWebSocketFactory = new class implements IWebSocketFactory { - connect(host: string, port: number, query: string, callback: IConnectCallback): void { - const errorListener = (err: any) => callback(err, undefined); -- const socket = new WebSocket(`ws://${host}:${port}/?${query}&skipWebSocketFrames=false`); -+ const socket = new WebSocket(`${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${window.location.host}${window.location.pathname}?${query}&skipWebSocketFrames=false`); - socket.onopen = function (event) { - socket.removeEventListener('error', errorListener); - callback(undefined, new BrowserSocket(socket)); -diff --git a/src/vs/platform/telemetry/node/telemetryIpc.ts b/src/vs/platform/telemetry/node/telemetryIpc.ts -index 8e1b68eb36..2b6a0d5b15 100644 ---- a/src/vs/platform/telemetry/node/telemetryIpc.ts -+++ b/src/vs/platform/telemetry/node/telemetryIpc.ts -@@ -6,6 +6,9 @@ - import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; - import { ITelemetryAppender } from 'vs/platform/telemetry/common/telemetryUtils'; - import { Event } from 'vs/base/common/event'; -+import { ITelemetryService, ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry'; -+import { ITelemetryData } from 'vs/base/common/actions'; -+import { ClassifiedEvent, GDPRClassification, StrictPropertyCheck } from 'vs/platform/telemetry/common/gdprTypings'; - - export interface ITelemetryLog { - eventName: string; -@@ -41,3 +44,52 @@ export class TelemetryAppenderClient implements ITelemetryAppender { - // TODO +diff --git a/src/vs/platform/remote/browser/browserSocketFactory.ts b/src/vs/platform/remote/browser/browserSocketFactory.ts +index 6b24ec0781..4d05c63193 100644 +--- a/src/vs/platform/remote/browser/browserSocketFactory.ts ++++ b/src/vs/platform/remote/browser/browserSocketFactory.ts +@@ -133,7 +133,7 @@ export class BrowserSocketFactory implements ISocketFactory { } - } -+ -+export class TelemetryChannel implements IServerChannel { -+ -+ constructor(private service: ITelemetryService) {} -+ -+ listen(_: unknown, event: string): Event { -+ throw new Error(`Invalid listen ${event}`); -+ } -+ -+ call(_: unknown, command: string, args?: any): Promise { -+ switch (command) { -+ case 'publicLog': return this.service.publicLog(args[0], args[1], args[2]); -+ case 'publicLog2': return this.service.publicLog2(args[0], args[1], args[2]); -+ case 'setEnabled': return Promise.resolve(this.service.setEnabled(args[0])); -+ case 'getTelemetryInfo': return this.service.getTelemetryInfo(); -+ } -+ -+ throw new Error(`Invalid call ${command}`); -+ } -+} -+ -+export class TelemetryChannelClient implements ITelemetryService { -+ -+ _serviceBrand: any; -+ -+ constructor( -+ private readonly channel: IChannel, -+ ) { } -+ -+ public publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): Promise { -+ return this.channel.call('publicLog', [eventName, data, anonymizeFilePaths]); -+ } -+ -+ public publicLog2 = never, T extends GDPRClassification = never>(eventName: string, data?: StrictPropertyCheck, anonymizeFilePaths?: boolean): Promise { -+ return this.channel.call('publicLog2', [eventName, data, anonymizeFilePaths]); -+ } -+ -+ public setEnabled(value: boolean): void { -+ this.channel.call('setEnable', [value]); -+ } -+ -+ public getTelemetryInfo(): Promise { -+ return this.channel.call('getTelemetryInfo'); -+ } -+ -+ public get isOptedIn(): boolean { -+ return true; -+ } -+} + + connect(host: string, port: number, query: string, callback: IConnectCallback): void { +- const socket = this._webSocketFactory.create(`ws://${host}:${port}/?${query}&skipWebSocketFrames=false`); ++ const socket = this._webSocketFactory.create(`${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${window.location.host}${window.location.pathname}?${query}&skipWebSocketFrames=false`); + const errorListener = socket.onError((err) => callback(err, undefined)); + socket.onOpen(() => { + errorListener.dispose(); +diff --git a/src/vs/platform/remote/common/remoteHosts.ts b/src/vs/platform/remote/common/remoteHosts.ts +index 5578246cc8..ba38bb0055 100644 +--- a/src/vs/platform/remote/common/remoteHosts.ts ++++ b/src/vs/platform/remote/common/remoteHosts.ts +@@ -6,7 +6,7 @@ + import { URI } from 'vs/base/common/uri'; + import { Schemas } from 'vs/base/common/network'; + +-export const REMOTE_HOST_SCHEME = Schemas.vscodeRemote; ++export const REMOTE_HOST_SCHEME = Schemas.codeServer; + + export function getRemoteAuthority(uri: URI): string | undefined { + return uri.scheme === REMOTE_HOST_SCHEME ? uri.authority : undefined; diff --git a/src/vs/platform/update/electron-browser/updateService.ts b/src/vs/platform/update/electron-browser/updateService.ts -index 023ea3ea7d..455df76ee3 100644 +index 952c39cdbe..fee00b3b39 100644 --- a/src/vs/platform/update/electron-browser/updateService.ts +++ b/src/vs/platform/update/electron-browser/updateService.ts -@@ -6,8 +6,9 @@ +@@ -6,7 +6,7 @@ import { IChannel } from 'vs/base/parts/ipc/common/ipc'; import { Event, Emitter } from 'vs/base/common/event'; import { IUpdateService, State } from 'vs/platform/update/common/update'; -import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService'; -+// import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService'; - import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; +import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; + import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; export class UpdateService implements IUpdateService { - -@@ -21,8 +22,11 @@ export class UpdateService implements IUpdateService { +@@ -21,8 +21,8 @@ export class UpdateService implements IUpdateService { private channel: IChannel; - constructor(@IMainProcessService mainProcessService: IMainProcessService) { - this.channel = mainProcessService.getChannel('update'); -+ constructor( -+ // @IMainProcessService mainProcessService: IMainProcessService -+ @IRemoteAgentService remoteAgentService: IRemoteAgentService -+ ) { -+ this.channel = remoteAgentService.getConnection()!.getChannel('update'); ++ constructor(@IRemoteAgentService mainProcessService: IRemoteAgentService) { ++ this.channel = mainProcessService.getConnection()!.getChannel('update'); // always set this._state as the state changes this.onStateChange(state => this._state = state); diff --git a/src/vs/platform/update/electron-main/abstractUpdateService.ts b/src/vs/platform/update/electron-main/abstractUpdateService.ts -index fcca3cbfb9..101f3d33c9 100644 +index 2a1240b1eb..342e9aa51d 100644 --- a/src/vs/platform/update/electron-main/abstractUpdateService.ts +++ b/src/vs/platform/update/electron-main/abstractUpdateService.ts -@@ -6,7 +6,7 @@ +@@ -6,7 +6,6 @@ import { Event, Emitter } from 'vs/base/common/event'; import { timeout } from 'vs/base/common/async'; import { IConfigurationService, getMigratedSettingValue } from 'vs/platform/configuration/common/configuration'; -import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; -+// import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; import product from 'vs/platform/product/node/product'; import { IUpdateService, State, StateType, AvailableForDownload, UpdateType } from 'vs/platform/update/common/update'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -@@ -40,7 +40,8 @@ export abstract class AbstractUpdateService implements IUpdateService { +@@ -44,7 +43,7 @@ export abstract class AbstractUpdateService implements IUpdateService { } constructor( - @ILifecycleService private readonly lifecycleService: ILifecycleService, + _placeholder: any, // To prevent errors from the extending classes. -+ // @ILifecycleService private readonly lifecycleService: ILifecycleService, @IConfigurationService protected configurationService: IConfigurationService, @IEnvironmentService private readonly environmentService: IEnvironmentService, @IRequestService protected requestService: IRequestService, -@@ -51,7 +52,7 @@ export abstract class AbstractUpdateService implements IUpdateService { +@@ -55,7 +54,7 @@ export abstract class AbstractUpdateService implements IUpdateService { return; } - if (!product.updateUrl || !product.commit) { -+ if (/*!product.updateUrl || */!product.commit) { ++ if (!product.commit) { this.logService.info('update#ctor - updates are disabled as there is no update URL'); return; } -@@ -82,7 +83,7 @@ export abstract class AbstractUpdateService implements IUpdateService { +@@ -86,7 +85,7 @@ export abstract class AbstractUpdateService implements IUpdateService { } private getProductQuality(updateMode: string): string | undefined { - return updateMode === 'none' ? undefined : product.quality; -+ return updateMode === 'none' ? undefined : 'quality'; ++ return updateMode === 'none' ? undefined : 'unused'; } private scheduleCheckForUpdates(delay = 60 * 60 * 1000): Promise { -@@ -141,15 +142,15 @@ export abstract class AbstractUpdateService implements IUpdateService { +@@ -145,15 +144,15 @@ export abstract class AbstractUpdateService implements IUpdateService { this.logService.trace('update#quitAndInstall(): before lifecycle quit()'); @@ -777,7 +475,7 @@ index fcca3cbfb9..101f3d33c9 100644 - if (vetod) { - return; - } -+ // this.quit(true /* from update */).then(vetod => { ++ // this.lifecycleService.quit(true /* from update */).then(vetod => { + // this.logService.trace(`update#quitAndInstall(): after lifecycle quit() with veto: ${vetod}`); + // if (vetod) { + // return; @@ -790,27 +488,14 @@ index fcca3cbfb9..101f3d33c9 100644 return Promise.resolve(undefined); } -diff --git a/src/vs/workbench/api/browser/viewsExtensionPoint.ts b/src/vs/workbench/api/browser/viewsExtensionPoint.ts -index 8bace46843..b261f40493 100644 ---- a/src/vs/workbench/api/browser/viewsExtensionPoint.ts -+++ b/src/vs/workbench/api/browser/viewsExtensionPoint.ts -@@ -327,7 +327,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution { - - // Generate CSS to show the icon in the activity bar - const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${cssClass}`; -- createCSSRule(iconClass, `-webkit-mask: url('${icon}') no-repeat 50% 50%`); -+ createCSSRule(iconClass, `-webkit-mask: url('${require.withBase(icon)}') no-repeat 50% 50%`); - } - - return viewContainer; diff --git a/src/vs/workbench/browser/dnd.ts b/src/vs/workbench/browser/dnd.ts -index 2054ceece3..f99dfd0b73 100644 +index cf1d6b5b60..be8fdb32f7 100644 --- a/src/vs/workbench/browser/dnd.ts +++ b/src/vs/workbench/browser/dnd.ts -@@ -31,6 +31,7 @@ import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsSe - import { IRecentFile } from 'vs/platform/history/common/history'; +@@ -32,6 +32,7 @@ import { IRecentFile } from 'vs/platform/history/common/history'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import { withNullAsUndefined } from 'vs/base/common/types'; + import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { IUploadService } from 'vs/server/src/upload'; export interface IDraggedResource { @@ -833,73 +518,19 @@ index 2054ceece3..f99dfd0b73 100644 } // Make the window active to handle the drop properly within -diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts -index 24d8fe70c7..0670ebb774 100644 ---- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts -+++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts -@@ -173,7 +173,7 @@ export class PlaceHolderViewletActivityAction extends ViewletActivityAction { - super({ id, name: id, cssClass: `extensionViewlet-placeholder-${id.replace(/\./g, '-')}` }, viewletService, layoutService, telemetryService); - - const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${this.class}`; // Generate Placeholder CSS to show the icon in the activity bar -- DOM.createCSSRule(iconClass, `-webkit-mask: url('${iconUrl || ''}') no-repeat 50% 50%`); -+ DOM.createCSSRule(iconClass, `-webkit-mask: url('${iconUrl ? require.withBase(iconUrl) : ''}') no-repeat 50% 50%`); - } - - setActivity(activity: IActivity): void { -diff --git a/src/vs/workbench/browser/parts/editor/resourceViewer.ts b/src/vs/workbench/browser/parts/editor/resourceViewer.ts -index a5e644112b..99f8271a59 100644 ---- a/src/vs/workbench/browser/parts/editor/resourceViewer.ts -+++ b/src/vs/workbench/browser/parts/editor/resourceViewer.ts -@@ -548,7 +548,7 @@ class InlineImageView { - const img = container.querySelector('img'); - if (img) { - if (typeof src === 'string') { -- img.src = src; -+ img.src = require.withBase(src); - } else { - const url = URL.createObjectURL(src); - disposables.add(toDisposable(() => URL.revokeObjectURL(url))); -diff --git a/src/vs/workbench/browser/parts/quickinput/quickInputUtils.ts b/src/vs/workbench/browser/parts/quickinput/quickInputUtils.ts -index babe949511..7bce969709 100644 ---- a/src/vs/workbench/browser/parts/quickinput/quickInputUtils.ts -+++ b/src/vs/workbench/browser/parts/quickinput/quickInputUtils.ts -@@ -22,8 +22,8 @@ export function getIconClass(iconPath: { dark: URI; light?: URI; } | undefined): - iconClass = iconPathToClass[key]; - } else { - iconClass = iconClassGenerator.nextId(); -- dom.createCSSRule(`.${iconClass}`, `background-image: url("${(iconPath.light || iconPath.dark).toString()}")`); -- dom.createCSSRule(`.vs-dark .${iconClass}, .hc-black .${iconClass}`, `background-image: url("${iconPath.dark.toString()}")`); -+ dom.createCSSRule(`.${iconClass}`, `background-image: url("${require.withBase(iconPath.light || iconPath.dark).toString()}")`); -+ dom.createCSSRule(`.vs-dark .${iconClass}, .hc-black .${iconClass}`, `background-image: url("${require.withBase(iconPath.dark).toString()}")`); - iconPathToClass[key] = iconClass; - } - -diff --git a/src/vs/workbench/browser/parts/views/customView.ts b/src/vs/workbench/browser/parts/views/customView.ts -index 5a758eb786..7fcacb5ca7 100644 ---- a/src/vs/workbench/browser/parts/views/customView.ts -+++ b/src/vs/workbench/browser/parts/views/customView.ts -@@ -674,7 +674,7 @@ class TreeRenderer implements IRenderer { - templateData.resourceLabel.setResource({ name: label, description }, { title, hideIcon: true, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches }); - } - -- templateData.icon.style.backgroundImage = iconUrl ? `url('${iconUrl.toString(true)}')` : ''; -+ templateData.icon.style.backgroundImage = iconUrl ? `url('${require.withBase(iconUrl).toString(true)}')` : ''; - DOM.toggleClass(templateData.icon, 'custom-view-tree-node-item-icon', !!iconUrl); - templateData.actionBar.context = ({ $treeViewId: this.treeViewId, $treeItemHandle: node.handle }); - templateData.actionBar.push(this.menus.getResourceActions(node), { icon: true, label: false }); diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts -index 1986fb6642..70b0c789e3 100644 +index ede771a03e..bb40fcdd6b 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts -@@ -35,6 +35,7 @@ import { SignService } from 'vs/platform/sign/browser/signService'; - import { hash } from 'vs/base/common/hash'; - import { IWorkbenchConstructionOptions } from 'vs/workbench/workbench.web.api'; - import { ProductService } from 'vs/platform/product/browser/productService'; +@@ -43,6 +43,7 @@ import { getThemeTypeSelector, DARK, HIGH_CONTRAST, LIGHT } from 'vs/platform/th + import { IRequestService } from 'vs/platform/request/common/request'; + import { RequestService } from 'vs/workbench/services/request/browser/requestService'; + import { InMemoryUserDataProvider } from 'vs/workbench/services/userData/common/inMemoryUserDataProvider'; +import { initialize } from 'vs/server/src/client'; class CodeRendererMain extends Disposable { -@@ -49,6 +50,7 @@ class CodeRendererMain extends Disposable { +@@ -57,6 +58,7 @@ class CodeRendererMain extends Disposable { async open(): Promise { const services = await this.initServices(); @@ -907,98 +538,35 @@ index 1986fb6642..70b0c789e3 100644 await domContentLoaded(); mark('willStartWorkbench'); -@@ -114,7 +116,8 @@ class CodeRendererMain extends Disposable { - const channel = connection.getChannel(REMOTE_FILE_SYSTEM_CHANNEL_NAME); +@@ -150,6 +152,8 @@ class CodeRendererMain extends Disposable { const remoteFileSystemProvider = this._register(new RemoteExtensionsFileSystemProvider(channel, remoteAgentService.getEnvironment())); -- fileService.registerProvider(Schemas.vscodeRemote, remoteFileSystemProvider); + fileService.registerProvider(Schemas.vscodeRemote, remoteFileSystemProvider); + fileService.registerProvider(Schemas.codeServer, remoteFileSystemProvider); + fileService.registerProvider(Schemas.file, remoteFileSystemProvider); - } - const payload = await this.resolveWorkspaceInitializationPayload(); + if (!userDataProvider) { + const remoteUserDataUri = this.getRemoteUserDataUri(); diff --git a/src/vs/workbench/browser/web.simpleservices.ts b/src/vs/workbench/browser/web.simpleservices.ts -index b253e573ae..164e50c3d1 100644 +index 25414d8733..73aca01cd2 100644 --- a/src/vs/workbench/browser/web.simpleservices.ts +++ b/src/vs/workbench/browser/web.simpleservices.ts -@@ -53,6 +53,14 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur - import { ParsedArgs } from 'vs/platform/environment/common/environment'; - import { ClassifiedEvent, StrictPropertyCheck, GDPRClassification } from 'vs/platform/telemetry/common/gdprTypings'; - import { IProcessEnvironment } from 'vs/base/common/platform'; -+import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; -+import { ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/node/extensionManagementIpc'; -+import { ExtensionGalleryChannelClient } from 'vs/platform/extensionManagement/node/extensionGalleryIpc'; -+import { TelemetryChannelClient } from 'vs/platform/telemetry/node/telemetryIpc'; -+import { IProductService } from 'vs/platform/product/common/product'; +@@ -38,6 +38,9 @@ import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteA + import { IExperimentService, IExperiment, ExperimentActionType, ExperimentState } from 'vs/workbench/contrib/experiments/common/experimentService'; + import { ExtensionHostDebugChannelClient, ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc'; + import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; ++import { ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc'; +import { IUploadService, UploadService } from 'vs/server/src/upload'; -+ +registerSingleton(IUploadService, UploadService, true); - //#region Backup File - -@@ -125,13 +133,11 @@ export class SimpleClipboardService implements IClipboardService { - writeText(text: string, type?: string): void { } - - readText(type?: string): string { -- // @ts-ignore -- return undefined; -+ throw new Error('not implemented'); - } - - readFindText(): string { -- // @ts-ignore -- return undefined; -+ throw new Error('not implemented'); - } - - writeFindText(text: string): void { } -@@ -239,7 +245,17 @@ export class SimpleExtensionGalleryService implements IExtensionGalleryService { - } - } - --registerSingleton(IExtensionGalleryService, SimpleExtensionGalleryService, true); -+// registerSingleton(IExtensionGalleryService, SimpleExtensionGalleryService, true); -+ -+class ExtensionGalleryService extends ExtensionGalleryChannelClient { -+ public constructor( -+ @IRemoteAgentService remoteAgentService: IRemoteAgentService, -+ @IProductService productService: IProductService, -+ ) { -+ super(remoteAgentService.getConnection()!.getChannel('gallery'), productService); -+ } -+} -+registerSingleton(IExtensionGalleryService, ExtensionGalleryService, true); - - //#endregion - -@@ -262,7 +278,7 @@ export class SimpleExtensionsWorkbenchService implements IExtensionsWorkbenchSer - checkForUpdates: any; - allowedBadgeProviders: string[]; - } --registerSingleton(IExtensionsWorkbenchService, SimpleExtensionsWorkbenchService, true); -+// registerSingleton(IExtensionsWorkbenchService, SimpleExtensionsWorkbenchService, true); - //#endregion - - //#region ICommentService -@@ -375,7 +391,10 @@ export class SimpleExtensionTipsService implements IExtensionTipsService { - } - - getAllIgnoredRecommendations(): { global: string[]; workspace: string[]; } { -- return Object.create(null); -+ return { -+ global: [], -+ workspace: [], -+ }; - } - } + //#region Extension Tips -@@ -436,7 +455,16 @@ export class SimpleExtensionManagementService implements IExtensionManagementSer +@@ -131,7 +134,15 @@ export class SimpleExtensionManagementService implements IExtensionManagementSer } } -registerSingleton(IExtensionManagementService, SimpleExtensionManagementService); +// registerSingleton(IExtensionManagementService, SimpleExtensionManagementService); -+ +class LocalExtensionManagementService extends ExtensionManagementChannelClient { + public constructor( + @IRemoteAgentService remoteAgentService: IRemoteAgentService, @@ -1010,24 +578,7 @@ index b253e573ae..164e50c3d1 100644 //#endregion -@@ -680,7 +708,15 @@ export class SimpleTelemetryService implements ITelemetryService { - } - } - --registerSingleton(ITelemetryService, SimpleTelemetryService); -+// registerSingleton(ITelemetryService, SimpleTelemetryService); -+class TelemetryService extends TelemetryChannelClient { -+ public constructor( -+ @IRemoteAgentService remoteAgentService: IRemoteAgentService, -+ ) { -+ super(remoteAgentService.getConnection()!.getChannel('telemetry')); -+ } -+} -+registerSingleton(ITelemetryService, TelemetryService); - - //#endregion - -@@ -714,7 +750,7 @@ export class SimpleUpdateService implements IUpdateService { +@@ -251,7 +262,7 @@ export class SimpleUpdateService implements IUpdateService { } } @@ -1036,25 +587,25 @@ index b253e573ae..164e50c3d1 100644 //#endregion -@@ -888,7 +924,7 @@ export class SimpleWindowService extends Disposable implements IWindowService { +@@ -491,7 +502,7 @@ export class SimpleWindowService extends Disposable implements IWindowService { for (let i = 0; i < _uris.length; i++) { const uri = _uris[i]; if ('folderUri' in uri) { -- const newAddress = `${document.location.origin}/?folder=${uri.folderUri.path}`; -+ const newAddress = require.withBase(`/?folder=${uri.folderUri.path}`); +- const newAddress = `${document.location.origin}/?folder=${uri.folderUri.path}${this.workbenchEnvironmentService.configuration.connectionToken ? `&tkn=${this.workbenchEnvironmentService.configuration.connectionToken}` : ''}`; ++ const newAddress = `${window.location}/?folder=${uri.folderUri.path}${this.workbenchEnvironmentService.configuration.connectionToken ? `&tkn=${this.workbenchEnvironmentService.configuration.connectionToken}` : ''}`; if (openFolderInNewWindow) { window.open(newAddress); } else { -@@ -896,7 +932,7 @@ export class SimpleWindowService extends Disposable implements IWindowService { +@@ -499,7 +510,7 @@ export class SimpleWindowService extends Disposable implements IWindowService { } } if ('workspaceUri' in uri) { - const newAddress = `${document.location.origin}/?workspace=${uri.workspaceUri.path}`; -+ const newAddress = require.withBase(`/?workspace=${uri.workspaceUri.path}`); ++ const newAddress = `${window.location}/?workspace=${uri.workspaceUri.path}`; if (openFolderInNewWindow) { window.open(newAddress); } else { -@@ -1100,6 +1136,7 @@ export class SimpleWindowsService implements IWindowsService { +@@ -718,6 +729,7 @@ export class SimpleWindowsService implements IWindowsService { } relaunch(_options: { addArgs?: string[], removeArgs?: string[] }): Promise { @@ -1062,475 +613,48 @@ index b253e573ae..164e50c3d1 100644 return Promise.resolve(); } -diff --git a/src/vs/workbench/contrib/comments/browser/commentNode.ts b/src/vs/workbench/contrib/comments/browser/commentNode.ts -index f4ac3fe8dd..3a3616b39e 100644 ---- a/src/vs/workbench/contrib/comments/browser/commentNode.ts -+++ b/src/vs/workbench/contrib/comments/browser/commentNode.ts -@@ -108,7 +108,7 @@ export class CommentNode extends Disposable { - const avatar = dom.append(this._domNode, dom.$('div.avatar-container')); - if (comment.userIconPath) { - const img = dom.append(avatar, dom.$('img.avatar')); -- img.src = comment.userIconPath.toString(); -+ img.src = require.withBase(comment.userIconPath).toString(); - img.onerror = _ => img.remove(); - } - this._commentDetailsContainer = dom.append(this._domNode, dom.$('.review-comment-contents')); -diff --git a/src/vs/workbench/contrib/comments/browser/reactionsAction.ts b/src/vs/workbench/contrib/comments/browser/reactionsAction.ts -index c14030dab8..42b666446d 100644 ---- a/src/vs/workbench/contrib/comments/browser/reactionsAction.ts -+++ b/src/vs/workbench/contrib/comments/browser/reactionsAction.ts -@@ -46,7 +46,7 @@ export class ReactionActionViewItem extends ActionViewItem { - let reactionIcon = dom.append(this.label, dom.$('.reaction-icon')); - reactionIcon.style.display = ''; - let uri = URI.revive(action.icon); -- reactionIcon.style.backgroundImage = `url('${uri}')`; -+ reactionIcon.style.backgroundImage = `url('${require.withBase(uri)}')`; - reactionIcon.title = action.label; - } - if (action.count) { -diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts -index 31b80683ee..720b649c01 100644 ---- a/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts -+++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts -@@ -108,8 +108,8 @@ export class ExtensionRenderer implements IListRenderer, index: number, data: IExtensionTemplateData): void { - const extension = node.element.extension; - const onError = Event.once(domEvent(data.icon, 'error')); -- onError(() => data.icon.src = extension.iconUrlFallback, null, data.extensionDisposables); -- data.icon.src = extension.iconUrl; -+ onError(() => data.icon.src = require.withBase(extension.iconUrlFallback), null, data.extensionDisposables); -+ data.icon.src = require.withBase(extension.iconUrl); - - if (!data.icon.complete) { - data.icon.style.visibility = 'hidden'; -diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionEditor.ts -index 86949eb39a..b7d04352ce 100644 ---- a/src/vs/workbench/contrib/extensions/electron-browser/extensionEditor.ts -+++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionEditor.ts -@@ -3,6 +3,7 @@ - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -+import * as process from 'vs/base/common/process'; - import 'vs/css!./media/extensionEditor'; - import { localize } from 'vs/nls'; +diff --git a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts +index d29d891120..6550d32c42 100644 +--- a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts ++++ b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts +@@ -8,7 +8,7 @@ import { localize } from 'vs/nls'; import * as marked from 'vs/base/common/marked/marked'; -@@ -28,8 +29,8 @@ import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, IExtension - import { RatingsWidget, InstallCountWidget, RemoteBadgeWidget } from 'vs/workbench/contrib/extensions/electron-browser/extensionsWidgets'; - import { EditorOptions } from 'vs/workbench/common/editor'; - import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; --import { CombinedInstallAction, UpdateAction, ExtensionEditorDropDownAction, ReloadAction, MaliciousStatusLabelAction, IgnoreExtensionRecommendationAction, UndoIgnoreExtensionRecommendationAction, EnableDropDownAction, DisableDropDownAction, StatusLabelAction, SetFileIconThemeAction, SetColorThemeAction, RemoteInstallAction, DisabledLabelAction, SystemDisabledWarningAction, LocalInstallAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions'; --import { WebviewElement } from 'vs/workbench/contrib/webview/electron-browser/webviewElement'; -+import { CombinedInstallAction, UpdateAction, ExtensionEditorDropDownAction, ReloadAction, MaliciousStatusLabelAction, IgnoreExtensionRecommendationAction, UndoIgnoreExtensionRecommendationAction, EnableDropDownAction, DisableDropDownAction, StatusLabelAction, SetFileIconThemeAction, SetColorThemeAction, /*RemoteInstallAction, */DisabledLabelAction, SystemDisabledWarningAction, LocalInstallAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions'; -+import { IFrameWebview as WebviewElement } from 'vs/workbench/contrib/webview/browser/webviewElement'; - import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; - import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; - import { IOpenerService } from 'vs/platform/opener/common/opener'; -@@ -44,7 +45,7 @@ import { assign } from 'vs/base/common/objects'; - import { INotificationService } from 'vs/platform/notification/common/notification'; - import { CancellationToken } from 'vs/base/common/cancellation'; - import { ExtensionsTree, ExtensionData } from 'vs/workbench/contrib/extensions/browser/extensionsViewer'; --import { ShowCurrentReleaseNotesAction } from 'vs/workbench/contrib/update/electron-browser/update'; -+// import { ShowCurrentReleaseNotesAction } from 'vs/workbench/contrib/update/electron-browser/update'; - import { KeybindingParser } from 'vs/base/common/keybindingParser'; - import { IStorageService } from 'vs/platform/storage/common/storage'; - import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -@@ -54,12 +55,12 @@ import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/work - import { URI } from 'vs/base/common/uri'; - - function renderBody(body: string): string { -- const styleSheetPath = require.toUrl('./media/markdown.css').replace('file://', 'vscode-resource://'); -+ const styleSheetPath = require.toUrl('./media/markdown.css'); - return ` + import { createCancelablePromise } from 'vs/base/common/async'; + import * as arrays from 'vs/base/common/arrays'; +-import { OS } from 'vs/base/common/platform'; ++import { OS, OperatingSystem } from 'vs/base/common/platform'; + import { Event, Emitter } from 'vs/base/common/event'; + import { Cache, CacheResult } from 'vs/base/common/cache'; + import { Action } from 'vs/base/common/actions'; +@@ -60,7 +60,7 @@ function renderBody(body: string): string { - -+ ++ -@@ -291,8 +292,8 @@ export class ExtensionEditor extends BaseEditor { - - const remoteBadge = this.instantiationService.createInstance(RemoteBadgeWidget, this.iconContainer, true); - const onError = Event.once(domEvent(this.icon, 'error')); -- onError(() => this.icon.src = extension.iconUrlFallback, null, this.transientDisposables); -- this.icon.src = extension.iconUrl; -+ onError(() => this.icon.src = require.withBase(extension.iconUrlFallback), null, this.transientDisposables); -+ this.icon.src = require.withBase(extension.iconUrl); - - this.name.textContent = extension.displayName; - this.identifier.textContent = extension.identifier.id; -@@ -370,7 +371,7 @@ export class ExtensionEditor extends BaseEditor { - this.instantiationService.createInstance(SetFileIconThemeAction, fileIconThemes), - this.instantiationService.createInstance(EnableDropDownAction), - this.instantiationService.createInstance(DisableDropDownAction, runningExtensions), -- this.instantiationService.createInstance(RemoteInstallAction), -+ // this.instantiationService.createInstance(RemoteInstallAction), - this.instantiationService.createInstance(LocalInstallAction), - combinedInstallAction, - systemDisabledWarningAction, -@@ -556,7 +557,7 @@ export class ExtensionEditor extends BaseEditor { - return; - } - // Whitelist supported schemes for links -- if (['http', 'https', 'mailto'].indexOf(link.scheme) >= 0 || (link.scheme === 'command' && link.path === ShowCurrentReleaseNotesAction.ID)) { -+ if (['http', 'https', 'mailto'].indexOf(link.scheme) >= 0 /*|| (link.scheme === 'command' && link.path === ShowCurrentReleaseNotesAction.ID)*/) { - this.openerService.open(link); - } - }, null, this.contentDisposables)); -diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts -index aa632ac96e..94ab4c042e 100644 ---- a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts -+++ b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts -@@ -9,10 +9,10 @@ import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes'; - import { Registry } from 'vs/platform/registry/common/platform'; - import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; - import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; --import { IExtensionTipsService, ExtensionsLabel, ExtensionsChannelId, PreferencesLabel, IExtensionManagementService, IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement'; -+import { /*IExtensionTipsService, */ExtensionsLabel, ExtensionsChannelId, PreferencesLabel, IExtensionManagementService, IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement'; - - import { IWorkbenchActionRegistry, Extensions as WorkbenchActionExtensions } from 'vs/workbench/common/actions'; --import { ExtensionTipsService } from 'vs/workbench/contrib/extensions/electron-browser/extensionTipsService'; -+// import { ExtensionTipsService } from 'vs/workbench/contrib/extensions/electron-browser/extensionTipsService'; - import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; - import { IOutputChannelRegistry, Extensions as OutputExtensions } from 'vs/workbench/contrib/output/common/output'; - import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -@@ -38,14 +38,14 @@ import { areSameExtensions } from 'vs/platform/extensionManagement/common/extens - import { GalleryExtensionsHandler, ExtensionsHandler } from 'vs/workbench/contrib/extensions/browser/extensionsQuickOpen'; - import { EditorDescriptor, IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; - import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; --import { RuntimeExtensionsEditor, ShowRuntimeExtensionsAction, IExtensionHostProfileService, DebugExtensionHostAction, StartExtensionHostProfileAction, StopExtensionHostProfileAction, CONTEXT_PROFILE_SESSION_STATE, SaveExtensionHostProfileAction, CONTEXT_EXTENSION_HOST_PROFILE_RECORDED } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor'; --import { EditorInput, IEditorInputFactory, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, ActiveEditorContext } from 'vs/workbench/common/editor'; --import { ExtensionHostProfileService } from 'vs/workbench/contrib/extensions/electron-browser/extensionProfileService'; -+// import { RuntimeExtensionsEditor, ShowRuntimeExtensionsAction, IExtensionHostProfileService, DebugExtensionHostAction, StartExtensionHostProfileAction, StopExtensionHostProfileAction, CONTEXT_PROFILE_SESSION_STATE, SaveExtensionHostProfileAction, CONTEXT_EXTENSION_HOST_PROFILE_RECORDED } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor'; -+import { EditorInput, IEditorInputFactory, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions/*, ActiveEditorContext*/ } from 'vs/workbench/common/editor'; -+// import { ExtensionHostProfileService } from 'vs/workbench/contrib/extensions/electron-browser/extensionProfileService'; - import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsInput'; - import { URI, UriComponents } from 'vs/base/common/uri'; --import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -+// import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; - import { ExtensionActivationProgress } from 'vs/workbench/contrib/extensions/browser/extensionsActivationProgress'; --import { ExtensionsAutoProfiler } from 'vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler'; -+// import { ExtensionsAutoProfiler } from 'vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler'; - import { onUnexpectedError } from 'vs/base/common/errors'; - import { ExtensionDependencyChecker } from 'vs/workbench/contrib/extensions/electron-browser/extensionsDependencyChecker'; - import { CancellationToken } from 'vs/base/common/cancellation'; -@@ -53,8 +53,8 @@ import { ExtensionType } from 'vs/platform/extensions/common/extensions'; - - // Singletons - registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService); --registerSingleton(IExtensionTipsService, ExtensionTipsService); --registerSingleton(IExtensionHostProfileService, ExtensionHostProfileService, true); -+// registerSingleton(IExtensionTipsService, ExtensionTipsService); -+// registerSingleton(IExtensionHostProfileService, ExtensionHostProfileService, true); - - const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); - workbenchRegistry.registerWorkbenchContribution(StatusUpdater, LifecyclePhase.Restored); -@@ -63,7 +63,7 @@ workbenchRegistry.registerWorkbenchContribution(ConfigureRecommendedExtensionsCo - workbenchRegistry.registerWorkbenchContribution(KeymapExtensions, LifecyclePhase.Restored); - workbenchRegistry.registerWorkbenchContribution(ExtensionsViewletViewsContribution, LifecyclePhase.Starting); - workbenchRegistry.registerWorkbenchContribution(ExtensionActivationProgress, LifecyclePhase.Eventually); --workbenchRegistry.registerWorkbenchContribution(ExtensionsAutoProfiler, LifecyclePhase.Eventually); -+// workbenchRegistry.registerWorkbenchContribution(ExtensionsAutoProfiler, LifecyclePhase.Eventually); - workbenchRegistry.registerWorkbenchContribution(ExtensionDependencyChecker, LifecyclePhase.Eventually); - - Registry.as(OutputExtensions.OutputChannels) -@@ -104,14 +104,14 @@ Registry.as(EditorExtensions.Editors) - - // Running Extensions Editor - --const runtimeExtensionsEditorDescriptor = new EditorDescriptor( -+/*const runtimeExtensionsEditorDescriptor = new EditorDescriptor( - RuntimeExtensionsEditor, - RuntimeExtensionsEditor.ID, - localize('runtimeExtension', "Running Extensions") - ); - - Registry.as(EditorExtensions.Editors) -- .registerEditor(runtimeExtensionsEditorDescriptor, [new SyncDescriptor(RuntimeExtensionsInput)]); -+ .registerEditor(runtimeExtensionsEditorDescriptor, [new SyncDescriptor(RuntimeExtensionsInput)]);*/ - - class RuntimeExtensionsInputFactory implements IEditorInputFactory { - serialize(editorInput: EditorInput): string { -@@ -203,7 +203,7 @@ actionRegistry.registerWorkbenchAction(checkForUpdatesAction, `Extensions: Check - actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(EnableAutoUpdateAction, EnableAutoUpdateAction.ID, EnableAutoUpdateAction.LABEL), `Extensions: Enable Auto Updating Extensions`, ExtensionsLabel); - actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(DisableAutoUpdateAction, DisableAutoUpdateAction.ID, DisableAutoUpdateAction.LABEL), `Extensions: Disable Auto Updating Extensions`, ExtensionsLabel); - actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(InstallSpecificVersionOfExtensionAction, InstallSpecificVersionOfExtensionAction.ID, InstallSpecificVersionOfExtensionAction.LABEL), 'Install Specific Version of Extension...', ExtensionsLabel); --actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ShowRuntimeExtensionsAction, ShowRuntimeExtensionsAction.ID, ShowRuntimeExtensionsAction.LABEL), 'Show Running Extensions', localize('developer', "Developer")); -+// actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ShowRuntimeExtensionsAction, ShowRuntimeExtensionsAction.ID, ShowRuntimeExtensionsAction.LABEL), 'Show Running Extensions', localize('developer', "Developer")); - actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ReinstallAction, ReinstallAction.ID, ReinstallAction.LABEL), 'Reinstall Extension...', localize('developer', "Developer")); - - Registry.as(ConfigurationExtensions.Configuration) -@@ -270,7 +270,7 @@ CommandsRegistry.registerCommand('extension.open', (accessor: ServicesAccessor, - }); - }); - --CommandsRegistry.registerCommand(DebugExtensionHostAction.ID, (accessor: ServicesAccessor) => { -+/*CommandsRegistry.registerCommand(DebugExtensionHostAction.ID, (accessor: ServicesAccessor) => { - const instantiationService = accessor.get(IInstantiationService); - instantiationService.createInstance(DebugExtensionHostAction).run(); - }); -@@ -288,7 +288,7 @@ CommandsRegistry.registerCommand(StopExtensionHostProfileAction.ID, (accessor: S - CommandsRegistry.registerCommand(SaveExtensionHostProfileAction.ID, (accessor: ServicesAccessor) => { - const instantiationService = accessor.get(IInstantiationService); - instantiationService.createInstance(SaveExtensionHostProfileAction, SaveExtensionHostProfileAction.ID, SaveExtensionHostProfileAction.LABEL).run(); --}); -+});*/ - - // File menu registration - -@@ -332,7 +332,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, { - - // Running extensions - --MenuRegistry.appendMenuItem(MenuId.EditorTitle, { -+/*MenuRegistry.appendMenuItem(MenuId.EditorTitle, { - command: { - id: DebugExtensionHostAction.ID, - title: DebugExtensionHostAction.LABEL, -@@ -383,7 +383,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { - }, - group: 'navigation', - when: ContextKeyExpr.and(ActiveEditorContext.isEqualTo(RuntimeExtensionsEditor.ID)) --}); -+}); */ - - CommandsRegistry.registerCommand({ - id: 'workbench.extensions.installExtension', -diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionsList.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionsList.ts -index 3f6427704d..8d2d78f537 100644 ---- a/src/vs/workbench/contrib/extensions/electron-browser/extensionsList.ts -+++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionsList.ts -@@ -13,7 +13,7 @@ import { IPagedRenderer } from 'vs/base/browser/ui/list/listPaging'; - import { Event } from 'vs/base/common/event'; - import { domEvent } from 'vs/base/browser/event'; - import { IExtension, ExtensionContainers, ExtensionState, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions'; --import { InstallAction, UpdateAction, ManageExtensionAction, ReloadAction, MaliciousStatusLabelAction, ExtensionActionViewItem, StatusLabelAction, RemoteInstallAction, SystemDisabledWarningAction, DisabledLabelAction, LocalInstallAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions'; -+import { InstallAction, UpdateAction, ManageExtensionAction, ReloadAction, MaliciousStatusLabelAction, ExtensionActionViewItem, StatusLabelAction, /*RemoteInstallAction, */SystemDisabledWarningAction, DisabledLabelAction, LocalInstallAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions'; - import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; - import { Label, RatingsWidget, InstallCountWidget, RecommendationWidget, RemoteBadgeWidget, TooltipWidget } from 'vs/workbench/contrib/extensions/electron-browser/extensionsWidgets'; - import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -@@ -96,7 +96,7 @@ export class Renderer implements IPagedRenderer { - this.instantiationService.createInstance(UpdateAction), - reloadAction, - this.instantiationService.createInstance(InstallAction), -- this.instantiationService.createInstance(RemoteInstallAction), -+ // this.instantiationService.createInstance(RemoteInstallAction), - this.instantiationService.createInstance(LocalInstallAction), - this.instantiationService.createInstance(MaliciousStatusLabelAction, false), - systemDisabledWarningAction, -@@ -165,8 +165,8 @@ export class Renderer implements IPagedRenderer { - this.extensionService.onDidChangeExtensions(() => updateEnablement(), this, data.extensionDisposables); - - const onError = Event.once(domEvent(data.icon, 'error')); -- onError(() => data.icon.src = extension.iconUrlFallback, null, data.extensionDisposables); -- data.icon.src = extension.iconUrl; -+ onError(() => data.icon.src = require.withBase(extension.iconUrlFallback), null, data.extensionDisposables); -+ data.icon.src = require.withBase(extension.iconUrl); - - if (!data.icon.complete) { - data.icon.style.visibility = 'hidden'; -diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionsViews.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionsViews.ts -index 6dad2fb580..04e5d2a62b 100644 ---- a/src/vs/workbench/contrib/extensions/electron-browser/extensionsViews.ts -+++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionsViews.ts -@@ -34,7 +34,7 @@ import { INotificationService, Severity } from 'vs/platform/notification/common/ - import { ViewletPanel, IViewletPanelOptions } from 'vs/workbench/browser/parts/views/panelViewlet'; - import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; - import { distinct, coalesce } from 'vs/base/common/arrays'; --import { IExperimentService, IExperiment, ExperimentActionType } from 'vs/workbench/contrib/experiments/electron-browser/experimentService'; -+import { /*IExperimentService, */IExperiment/*, ExperimentActionType*/ } from 'vs/workbench/contrib/experiments/electron-browser/experimentService'; - import { alert } from 'vs/base/browser/ui/aria/aria'; - import { IListContextMenuEvent } from 'vs/base/browser/ui/list/list'; - import { createErrorWithActions } from 'vs/base/common/errorsWithActions'; -@@ -96,7 +96,7 @@ export class ExtensionsListView extends ViewletPanel { - @ITelemetryService private readonly telemetryService: ITelemetryService, - @IConfigurationService configurationService: IConfigurationService, - @IWorkspaceContextService protected contextService: IWorkspaceContextService, -- @IExperimentService private readonly experimentService: IExperimentService, -+ // @IExperimentService private readonly experimentService: IExperimentService, - @IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService, - @IExtensionManagementServerService protected readonly extensionManagementServerService: IExtensionManagementServerService, - @IProductService protected readonly productService: IProductService, -@@ -483,7 +483,7 @@ export class ExtensionsListView extends ViewletPanel { - private _searchExperiments: Promise; - private getSearchExperiments(): Promise { - if (!this._searchExperiments) { -- this._searchExperiments = this.experimentService.getExperimentsByType(ExperimentActionType.ExtensionSearchResults); -+ this._searchExperiments = Promise.resolve([]); // this.experimentService.getExperimentsByType(ExperimentActionType.ExtensionSearchResults); +@@ -1076,10 +1076,10 @@ export class ExtensionEditor extends BaseEditor { + private resolveKeybinding(rawKeyBinding: IKeyBinding): ResolvedKeybinding | null { + let key: string | undefined; + +- switch (process.platform) { +- case 'win32': key = rawKeyBinding.win; break; +- case 'linux': key = rawKeyBinding.linux; break; +- case 'darwin': key = rawKeyBinding.mac; break; ++ switch (OS) { ++ case OperatingSystem.Windows: key = rawKeyBinding.win; break; ++ case OperatingSystem.Linux: key = rawKeyBinding.linux; break; ++ case OperatingSystem.Macintosh: key = rawKeyBinding.mac; break; } - return this._searchExperiments; - } -@@ -552,7 +552,7 @@ export class ExtensionsListView extends ViewletPanel { - - private async getCuratedModel(query: Query, options: IQueryOptions, token: CancellationToken): Promise> { - const value = query.value.replace(/curated:/g, '').trim(); -- const names = await this.experimentService.getCuratedExtensionsList(value); -+ const names = []; // await this.experimentService.getCuratedExtensionsList(value); - if (Array.isArray(names) && names.length) { - options.source = `curated:${value}`; - const pager = await this.extensionsWorkbenchService.queryGallery(assign(options, { names, pageSize: names.length }), token); -@@ -843,14 +843,14 @@ export class ServerExtensionsView extends ExtensionsListView { - @ITelemetryService telemetryService: ITelemetryService, - @IConfigurationService configurationService: IConfigurationService, - @IWorkspaceContextService contextService: IWorkspaceContextService, -- @IExperimentService experimentService: IExperimentService, -+ // @IExperimentService experimentService: IExperimentService, - @IWorkbenchThemeService workbenchThemeService: IWorkbenchThemeService, - @IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService, - @IExtensionManagementServerService extensionManagementServerService: IExtensionManagementServerService, - @IProductService productService: IProductService, - ) { - options.server = server; -- super(options, notificationService, keybindingService, contextMenuService, instantiationService, themeService, extensionService, extensionsWorkbenchService, editorService, tipsService, telemetryService, configurationService, contextService, experimentService, workbenchThemeService, extensionManagementServerService, productService); -+ super(options, notificationService, keybindingService, contextMenuService, instantiationService, themeService, extensionService, extensionsWorkbenchService, editorService, tipsService, telemetryService, configurationService, contextService, /*experimentService,*/ workbenchThemeService, extensionManagementServerService, productService); - this._register(onDidChangeTitle(title => this.updateTitle(title))); - } - -diff --git a/src/vs/workbench/contrib/extensions/node/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/node/extensionsWorkbenchService.ts -index c08a6e37c1..2e1deb01e6 100644 ---- a/src/vs/workbench/contrib/extensions/node/extensionsWorkbenchService.ts -+++ b/src/vs/workbench/contrib/extensions/node/extensionsWorkbenchService.ts -@@ -4,7 +4,7 @@ - *--------------------------------------------------------------------------------------------*/ - import * as nls from 'vs/nls'; --import * as semver from 'semver'; -+// import * as semver from 'semver'; - import { Event, Emitter } from 'vs/base/common/event'; - import { index, distinct } from 'vs/base/common/arrays'; - import { ThrottledDelayer } from 'vs/base/common/async'; -@@ -26,7 +26,7 @@ import { IExtension, ExtensionState, IExtensionsWorkbenchService, AutoUpdateConf - import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService'; - import { IURLService, IURLHandler } from 'vs/platform/url/common/url'; - import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput'; --import product from 'vs/platform/product/node/product'; -+import { IProductService } from 'vs/platform/product/common/product'; // import product from 'vs/platform/product/node/product'; - import { ILogService } from 'vs/platform/log/common/log'; - import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; - import { INotificationService } from 'vs/platform/notification/common/notification'; -@@ -53,7 +53,8 @@ class Extension implements IExtension { - public gallery: IGalleryExtension | undefined, - private telemetryService: ITelemetryService, - private logService: ILogService, -- private fileService: IFileService -+ private fileService: IFileService, -+ private productService: IProductService, - ) { } - - get type(): ExtensionType | undefined { -@@ -112,11 +113,11 @@ class Extension implements IExtension { - } - - get url(): string | undefined { -- if (!product.extensionsGallery || !this.gallery) { -+ if (!this.productService.extensionsGallery || !this.gallery) { - return undefined; - } - -- return `${product.extensionsGallery.itemUrl}?itemName=${this.publisher}.${this.name}`; -+ return `${this.productService.extensionsGallery.itemUrl}?itemName=${this.publisher}.${this.name}`; - } - - get iconUrl(): string { -@@ -183,7 +184,7 @@ class Extension implements IExtension { - } - - get outdated(): boolean { -- return !!this.gallery && this.type === ExtensionType.User && semver.gt(this.latestVersion, this.version); -+ return !!this.gallery && this.type === ExtensionType.User && this.latestVersion !== this.version; - } - - get telemetryData(): any { -@@ -201,7 +202,7 @@ class Extension implements IExtension { - } - - private isGalleryOutdated(): boolean { -- return this.local && this.gallery ? semver.gt(this.local.manifest.version, this.gallery.version) : false; -+ return this.local && this.gallery ? this.local.manifest.version !== this.gallery.version : false; - } - - getManifest(token: CancellationToken): Promise { -@@ -320,7 +321,8 @@ class Extensions extends Disposable { - @ITelemetryService private readonly telemetryService: ITelemetryService, - @ILogService private readonly logService: ILogService, - @IFileService private readonly fileService: IFileService, -- @IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService -+ @IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService, -+ @IProductService private readonly productService: IProductService - ) { - super(); - this._register(server.extensionManagementService.onInstallExtension(e => this.onInstallExtension(e))); -@@ -342,7 +344,7 @@ class Extensions extends Disposable { - const installed = await this.server.extensionManagementService.getInstalled(); - const byId = index(this.installed, e => e.local ? e.local.identifier.id : e.identifier.id); - this.installed = installed.map(local => { -- const extension = byId[local.identifier.id] || new Extension(this.galleryService, this.stateProvider, this.server, local, undefined, this.telemetryService, this.logService, this.fileService); -+ const extension = byId[local.identifier.id] || new Extension(this.galleryService, this.stateProvider, this.server, local, undefined, this.telemetryService, this.logService, this.fileService, this.productService); - extension.local = local; - extension.enablementState = this.extensionEnablementService.getEnablementState(local); - return extension; -@@ -395,7 +397,7 @@ class Extensions extends Disposable { - const { gallery } = event; - if (gallery) { - const extension = this.installed.filter(e => areSameExtensions(e.identifier, gallery.identifier))[0] -- || new Extension(this.galleryService, this.stateProvider, this.server, undefined, gallery, this.telemetryService, this.logService, this.fileService); -+ || new Extension(this.galleryService, this.stateProvider, this.server, undefined, gallery, this.telemetryService, this.logService, this.fileService, this.productService); - this.installing.push(extension); - this._onChange.fire(extension); - } -@@ -406,7 +408,7 @@ class Extensions extends Disposable { - const installingExtension = gallery ? this.installing.filter(e => areSameExtensions(e.identifier, gallery.identifier))[0] : null; - this.installing = installingExtension ? this.installing.filter(e => e !== installingExtension) : this.installing; - -- let extension: Extension | undefined = installingExtension ? installingExtension : zipPath ? new Extension(this.galleryService, this.stateProvider, this.server, local, undefined, this.telemetryService, this.logService, this.fileService) : undefined; -+ let extension: Extension | undefined = installingExtension ? installingExtension : zipPath ? new Extension(this.galleryService, this.stateProvider, this.server, local, undefined, this.telemetryService, this.logService, this.fileService, this.productService) : undefined; - if (extension) { - if (local) { - const installed = this.installed.filter(e => areSameExtensions(e.identifier, extension!.identifier))[0]; -@@ -501,7 +503,8 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension - @IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService, - @IStorageService private readonly storageService: IStorageService, - @IFileService private readonly fileService: IFileService, -- @IModeService private readonly modeService: IModeService -+ @IModeService private readonly modeService: IModeService, -+ @IProductService private readonly productService: IProductService - ) { - super(); - this.localExtensions = this._register(instantiationService.createInstance(Extensions, extensionManagementServerService.localExtensionManagementServer, ext => this.getExtensionState(ext))); -@@ -606,7 +609,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension - text = text.replace(extensionRegex, (m, ext) => { - - // Get curated keywords -- const lookup = product.extensionKeywords || {}; -+ const lookup: {[extension: string]: string[]} = /*this.productService.extensionKeywords || */{}; - const keywords = lookup[ext] || []; - - // Get mode name -@@ -649,7 +652,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension - if (installed) { - return installed; - } -- const extension = new Extension(this.galleryService, ext => this.getExtensionState(ext), undefined, undefined, gallery, this.telemetryService, this.logService, this.fileService); -+ const extension = new Extension(this.galleryService, ext => this.getExtensionState(ext), undefined, undefined, gallery, this.telemetryService, this.logService, this.fileService, this.productService); - if (maliciousExtensionSet.has(extension.identifier.id)) { - extension.isMalicious = true; - } -@@ -999,7 +1002,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension - - get allowedBadgeProviders(): string[] { - if (!this._extensionAllowedBadgeProviders) { -- this._extensionAllowedBadgeProviders = (product.extensionAllowedBadgeProviders || []).map(s => s.toLowerCase()); -+ this._extensionAllowedBadgeProviders = []; // (product.extensionAllowedBadgeProviders || []).map(s => s.toLowerCase()); - } - return this._extensionAllowedBadgeProviders; - } + const keyBinding = KeybindingParser.parseKeybinding(key || rawKeyBinding.key, OS); diff --git a/src/vs/workbench/contrib/files/browser/files.contribution.ts b/src/vs/workbench/contrib/files/browser/files.contribution.ts -index 88ad0027e9..17476d5f26 100644 +index b219a608bd..f35f5fa410 100644 --- a/src/vs/workbench/contrib/files/browser/files.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/files.contribution.ts -@@ -200,7 +200,7 @@ configurationRegistry.registerConfiguration({ +@@ -224,7 +224,7 @@ configurationRegistry.registerConfiguration({ 'files.exclude': { 'type': 'object', 'markdownDescription': nls.localize('exclude', "Configure glob patterns for excluding files and folders. For example, the files explorer decides which files and folders to show or hide based on this setting. Read more about glob patterns [here](https://code.visualstudio.com/docs/editor/codebasics#_advanced-search-options)."), @@ -1540,7 +664,7 @@ index 88ad0027e9..17476d5f26 100644 'additionalProperties': { 'anyOf': [ diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts -index 4592b3918e..346292d086 100644 +index 6543070e81..3d2780f1ba 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -46,6 +46,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic @@ -1583,98 +707,71 @@ index 9235c739fb..32d203eb32 100644 this._register(logService.onDidChangeLogLevel(level => logLevelClient.setLevel(level))); } } -diff --git a/src/vs/workbench/contrib/scm/browser/scmViewlet.ts b/src/vs/workbench/contrib/scm/browser/scmViewlet.ts -index 4d8a5d6907..b464d5276f 100644 ---- a/src/vs/workbench/contrib/scm/browser/scmViewlet.ts -+++ b/src/vs/workbench/contrib/scm/browser/scmViewlet.ts -@@ -497,7 +497,7 @@ class ResourceRenderer implements IListRenderer - - if (icon) { - template.decorationIcon.style.display = ''; -- template.decorationIcon.style.backgroundImage = `url('${icon}')`; -+ template.decorationIcon.style.backgroundImage = `url('${require.withBase(icon)}')`; - template.decorationIcon.title = resource.decorations.tooltip || ''; - } else { - template.decorationIcon.style.display = 'none'; diff --git a/src/vs/workbench/contrib/update/electron-browser/update.contribution.ts b/src/vs/workbench/contrib/update/electron-browser/update.contribution.ts -index e39fa57979..d0548847a4 100644 +index e39fa57979..3c775c9a06 100644 --- a/src/vs/workbench/contrib/update/electron-browser/update.contribution.ts +++ b/src/vs/workbench/contrib/update/electron-browser/update.contribution.ts -@@ -4,26 +4,26 @@ +@@ -4,26 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/platform/update/node/update.config.contribution'; -import * as platform from 'vs/base/common/platform'; -+// import * as platform from 'vs/base/common/platform'; import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; -import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; -import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -import { ShowCurrentReleaseNotesAction, ProductContribution, UpdateContribution, Win3264BitContribution } from './update'; -+// import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; -+// import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -+import { /*ShowCurrentReleaseNotesAction, ProductContribution, */UpdateContribution/*, Win3264BitContribution */} from './update'; ++import { UpdateContribution } from './update'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; const workbench = Registry.as(WorkbenchExtensions.Workbench); -workbench.registerWorkbenchContribution(ProductContribution, LifecyclePhase.Restored); -+/* workbench.registerWorkbenchContribution(ProductContribution, LifecyclePhase.Restored); - - if (platform.isWindows) { - if (process.arch === 'ia32') { - workbench.registerWorkbenchContribution(Win3264BitContribution, LifecyclePhase.Restored); - } +- +-if (platform.isWindows) { +- if (process.arch === 'ia32') { +- workbench.registerWorkbenchContribution(Win3264BitContribution, LifecyclePhase.Restored); +- } -} -+} */ - +- workbench.registerWorkbenchContribution(UpdateContribution, LifecyclePhase.Restored); - - // Editor +- +-// Editor -Registry.as(ActionExtensions.WorkbenchActions) - .registerWorkbenchAction(new SyncActionDescriptor(ShowCurrentReleaseNotesAction, ShowCurrentReleaseNotesAction.ID, ShowCurrentReleaseNotesAction.LABEL), 'Show Release Notes'); -+// Registry.as(ActionExtensions.WorkbenchActions) -+// .registerWorkbenchAction(new SyncActionDescriptor(ShowCurrentReleaseNotesAction, ShowCurrentReleaseNotesAction.ID, ShowCurrentReleaseNotesAction.LABEL), 'Show Release Notes'); diff --git a/src/vs/workbench/contrib/update/electron-browser/update.ts b/src/vs/workbench/contrib/update/electron-browser/update.ts -index 7078a1bb2f..94b1ce31a7 100644 +index 0d2d53003b..03489411bb 100644 --- a/src/vs/workbench/contrib/update/electron-browser/update.ts +++ b/src/vs/workbench/contrib/update/electron-browser/update.ts -@@ -7,32 +7,33 @@ import * as nls from 'vs/nls'; +@@ -7,34 +7,24 @@ import * as nls from 'vs/nls'; import severity from 'vs/base/common/severity'; import { Action } from 'vs/base/common/actions'; - import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; + import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle'; -import pkg from 'vs/platform/product/node/package'; -import product from 'vs/platform/product/node/product'; -import { URI } from 'vs/base/common/uri'; -+// import pkg from 'vs/platform/product/node/package'; -+// import product from 'vs/platform/product/node/product'; -+// import { URI } from 'vs/base/common/uri'; import { IActivityService, NumberBadge, IBadge, ProgressBadge } from 'vs/workbench/services/activity/common/activity'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +// import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { GLOBAL_ACTIVITY_ID } from 'vs/workbench/common/activity'; -import { IOpenerService } from 'vs/platform/opener/common/opener'; -+// import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IUpdateService, State as UpdateState, StateType, IUpdate } from 'vs/platform/update/common/update'; --import * as semver from 'semver'; +-import * as semver from 'semver-umd'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -+// import * as semver from 'semver'; -+// import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { INotificationService, INotificationHandle, Severity } from 'vs/platform/notification/common/notification'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { ReleaseNotesManager } from './releaseNotesEditor'; -import { isWindows } from 'vs/base/common/platform'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -+// import { ReleaseNotesManager } from './releaseNotesEditor'; -+// import { isWindows } from 'vs/base/common/platform'; -+// import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { FalseContext } from 'vs/platform/contextkey/common/contextkeys'; +-import { ShowCurrentReleaseNotesActionId } from 'vs/workbench/contrib/update/common/update'; +-import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows'; +import { IProductService } from 'vs/platform/product/common/product'; const CONTEXT_UPDATE_STATE = new RawContextKey('updateState', StateType.Uninitialized); @@ -1684,44 +781,51 @@ index 7078a1bb2f..94b1ce31a7 100644 function showReleaseNotes(instantiationService: IInstantiationService, version: string) { if (!releaseNotesManager) { -@@ -150,7 +151,7 @@ export class ProductContribution implements IWorkbenchContribution { - - storageService.store(ProductContribution.KEY, pkg.version, StorageScope.GLOBAL); +@@ -160,7 +150,7 @@ export class ProductContribution implements IWorkbenchContribution { + storageService.store(ProductContribution.KEY, pkg.version, StorageScope.GLOBAL); + }); } -} +} */ class NeverShowAgain { -@@ -175,7 +176,7 @@ class NeverShowAgain { +@@ -185,7 +175,7 @@ class NeverShowAgain { } } -export class Win3264BitContribution implements IWorkbenchContribution { -+/* export class Win3264BitContribution implements IWorkbenchContribution { ++/*export class Win3264BitContribution implements IWorkbenchContribution { private static readonly KEY = 'update/win32-64bits'; private static readonly URL = 'https://code.visualstudio.com/updates/v1_15#_windows-64-bit'; -@@ -214,7 +215,7 @@ export class Win3264BitContribution implements IWorkbenchContribution { +@@ -224,7 +214,7 @@ export class Win3264BitContribution implements IWorkbenchContribution { { sticky: true } ); } -} -+} */ ++}*/ export class UpdateContribution extends Disposable implements IWorkbenchContribution { -@@ -224,7 +225,8 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu +@@ -234,13 +224,14 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu constructor( @IStorageService private readonly storageService: IStorageService, - @IInstantiationService private readonly instantiationService: IInstantiationService, + // @IInstantiationService private readonly instantiationService: IInstantiationService, -+ @IProductService private readonly productService: IProductService, @INotificationService private readonly notificationService: INotificationService, @IDialogService private readonly dialogService: IDialogService, @IUpdateService private readonly updateService: IUpdateService, -@@ -247,7 +249,7 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu + @IActivityService private readonly activityService: IActivityService, + @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, +- @IContextKeyService private readonly contextKeyService: IContextKeyService ++ @IContextKeyService private readonly contextKeyService: IContextKeyService, ++ @IProductService private readonly productService: IProductService, + ) { + super(); + this.state = updateService.state; +@@ -257,7 +248,7 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu updated since 5 days. */ @@ -1730,7 +834,7 @@ index 7078a1bb2f..94b1ce31a7 100644 const lastKnownVersion = this.storageService.get('update/lastKnownVersion', StorageScope.GLOBAL); // if current version != stored version, clear both fields -@@ -292,9 +294,9 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu +@@ -302,9 +293,9 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu let clazz: string | undefined; if (state.type === StateType.AvailableForDownload || state.type === StateType.Downloaded || state.type === StateType.Ready) { @@ -1742,16 +846,7 @@ index 7078a1bb2f..94b1ce31a7 100644 clazz = 'progress-badge'; } -@@ -333,21 +335,21 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu - - this.notificationService.prompt( - severity.Info, -- nls.localize('thereIsUpdateAvailable', "There is an available update."), -+ nls.localize('updateAvailable', "There's an update available: {0} {1}", this.productService.nameLong, update.productVersion), - [{ -- label: nls.localize('download update', "Download Update"), -+ label: nls.localize('installUpdate', "Install Update"), - run: () => this.updateService.downloadUpdate() +@@ -350,14 +341,14 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu }, { label: nls.localize('later', "Later"), run: () => { } @@ -1768,7 +863,7 @@ index 7078a1bb2f..94b1ce31a7 100644 { sticky: true } ); } -@@ -360,30 +362,30 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu +@@ -370,30 +361,27 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu this.notificationService.prompt( severity.Info, @@ -1799,13 +894,10 @@ index 7078a1bb2f..94b1ce31a7 100644 - if (isWindows && product.target === 'user') { - return; - } -+ // if (isWindows && product.target === 'user') { -+ // return; -+ // } // windows fast updates (target === system) const neverShowAgain = new NeverShowAgain('update/win32-fast-updates', this.storageService); -@@ -394,7 +396,7 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu +@@ -404,7 +392,7 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu const handle = this.notificationService.prompt( severity.Info, @@ -1814,24 +906,18 @@ index 7078a1bb2f..94b1ce31a7 100644 [{ label: nls.localize('neveragain', "Don't Show Again"), isSecondary: true, -@@ -408,20 +410,23 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu +@@ -418,20 +406,17 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu // windows and mac private onUpdateReady(update: IUpdate): void { - if (!(isWindows && product.target !== 'user') && !this.shouldShowNotification()) { - return; - } -+ // if (!(isWindows && product.target !== 'user') && !this.shouldShowNotification()) { -+ // return; -+ // } const actions = [{ label: nls.localize('updateNow', "Update Now"), - run: () => this.updateService.quitAndInstall() -+ run: () => { -+ this.updateService.quitAndInstall(); -+ window.location.reload(); -+ } ++ run: () => { this.updateService.quitAndInstall(); window.location.reload(); } }, { label: nls.localize('later', "Later"), run: () => { } @@ -1843,7 +929,7 @@ index 7078a1bb2f..94b1ce31a7 100644 actions.push({ label: nls.localize('releaseNotes', "Release Notes"), run: () => { -@@ -430,19 +435,19 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu +@@ -440,19 +425,19 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu action.dispose(); } }); @@ -1866,7 +952,7 @@ index 7078a1bb2f..94b1ce31a7 100644 const currentMillis = new Date().getTime(); const lastKnownVersion = this.storageService.get('update/lastKnownVersion', StorageScope.GLOBAL); -@@ -485,7 +490,7 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu +@@ -495,7 +480,7 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu group: '5_update', command: { id: 'update.downloadNow', @@ -1875,214 +961,61 @@ index 7078a1bb2f..94b1ce31a7 100644 }, when: CONTEXT_UPDATE_STATE.isEqualTo(StateType.AvailableForDownload) }); -@@ -522,7 +527,10 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu +@@ -532,7 +517,7 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu when: CONTEXT_UPDATE_STATE.isEqualTo(StateType.Updating) }); - CommandsRegistry.registerCommand('update.restart', () => this.updateService.quitAndInstall()); -+ CommandsRegistry.registerCommand('update.restart', () => { -+ this.updateService.quitAndInstall(); -+ window.location.reload(); -+ }); ++ CommandsRegistry.registerCommand('update.restart', () => { this.updateService.quitAndInstall(); window.location.reload(); }); MenuRegistry.appendMenuItem(MenuId.GlobalActivity, { group: '5_update', command: { -diff --git a/src/vs/workbench/contrib/webview/browser/pre/main.js b/src/vs/workbench/contrib/webview/browser/pre/main.js -index a6be033e07..a4dcb7357a 100644 ---- a/src/vs/workbench/contrib/webview/browser/pre/main.js -+++ b/src/vs/workbench/contrib/webview/browser/pre/main.js -@@ -355,7 +355,7 @@ - // seeing the service worker applying properly. - // Fake load an empty on the correct origin and then write real html - // into it to get around this. -- newFrame.src = `/fake.html?id=${ID}`; -+ newFrame.src = `fake.html?id=${ID}`; - } - newFrame.style.cssText = 'display: block; margin: 0; overflow: hidden; position: absolute; width: 100%; height: 100%; visibility: hidden'; - document.body.appendChild(newFrame); -diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts -index 6d4d096a9c..bbb7930e7a 100644 ---- a/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts -+++ b/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts -@@ -39,10 +39,10 @@ export class WebviewEditorInput extends EditorInput { - this._icons.forEach((value, key) => { - const webviewSelector = `.show-file-icons .webview-${key}-name-file-icon::before`; - if (URI.isUri(value)) { -- cssRules.push(`${webviewSelector} { content: ""; background-image: url(${value.toString()}); }`); -+ cssRules.push(`${webviewSelector} { content: ""; background-image: url(${require.withBase(value).toString()}); }`); - } else { -- cssRules.push(`.vs ${webviewSelector} { content: ""; background-image: url(${value.light.toString()}); }`); -- cssRules.push(`.vs-dark ${webviewSelector} { content: ""; background-image: url(${value.dark.toString()}); }`); -+ cssRules.push(`.vs ${webviewSelector} { content: ""; background-image: url(${require.withBase(value.light).toString()}); }`); -+ cssRules.push(`.vs-dark ${webviewSelector} { content: ""; background-image: url(${require.withBase(value.dark).toString()}); }`); - } - }); - this._styleElement.innerHTML = cssRules.join('\n'); +diff --git a/src/vs/workbench/contrib/webview/browser/pre/index.html b/src/vs/workbench/contrib/webview/browser/pre/index.html +index ac53ce590e..2ce2b9d9f2 100644 +--- a/src/vs/workbench/contrib/webview/browser/pre/index.html ++++ b/src/vs/workbench/contrib/webview/browser/pre/index.html +@@ -4,7 +4,7 @@ + + + ++ content="default-src 'none'; script-src 'self'; frame-src 'self'; style-src 'self' 'unsafe-inline'; worker-src 'self'; img-src https: data:;" /> + + + +@@ -16,4 +16,4 @@ + + + +- +\ No newline at end of file ++ diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts -index 3525569601..a91a5fce7d 100644 +index 73e8b7c1d1..653d88e4f4 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts -@@ -136,6 +136,8 @@ export class BrowserWorkbenchEnvironmentService implements IEnvironmentService { - driverHandle?: string; +@@ -176,6 +176,8 @@ export class BrowserWorkbenchEnvironmentService implements IEnvironmentService { driverVerbose: boolean; webviewEndpoint?: string; + galleryMachineIdResource?: URI; + extraExtensionPaths: string[]; + extraBuiltinExtensionPaths: string[]; get webviewResourceRoot(): string { - return this.webviewEndpoint ? this.webviewEndpoint + '/vscode-resource' : 'vscode-resource:'; -diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionManagementServerService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionManagementServerService.ts -index 611ab9aec9..820cc92c73 100644 ---- a/src/vs/workbench/services/extensions/electron-browser/extensionManagementServerService.ts -+++ b/src/vs/workbench/services/extensions/electron-browser/extensionManagementServerService.ts -@@ -6,15 +6,15 @@ - import { localize } from 'vs/nls'; - import { Schemas } from 'vs/base/common/network'; - import { URI } from 'vs/base/common/uri'; --import { IExtensionManagementServer, IExtensionManagementServerService, IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement'; --import { ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/node/extensionManagementIpc'; -+import { IExtensionManagementServer, IExtensionManagementServerService, IExtensionGalleryService, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; -+// import { ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/node/extensionManagementIpc'; - import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; - import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts'; --import { IChannel } from 'vs/base/parts/ipc/common/ipc'; --import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; -+// import { IChannel } from 'vs/base/parts/ipc/common/ipc'; -+// import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; - import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; - import { ILogService } from 'vs/platform/log/common/log'; --import { RemoteExtensionManagementChannelClient } from 'vs/workbench/services/extensions/electron-browser/remoteExtensionManagementIpc'; -+// import { RemoteExtensionManagementChannelClient } from 'vs/workbench/services/extensions/electron-browser/remoteExtensionManagementIpc'; - import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; - import { IProductService } from 'vs/platform/product/common/product'; - -@@ -28,24 +28,26 @@ export class ExtensionManagementServerService implements IExtensionManagementSer - readonly remoteExtensionManagementServer: IExtensionManagementServer | null = null; - - constructor( -- @ISharedProcessService sharedProcessService: ISharedProcessService, -+ // This is set to `any` just to keep the tests from showing errors. -+ @IExtensionManagementService localExtensionManagementService: any, // @ISharedProcessService sharedProcessService: ISharedProcessService, - @IRemoteAgentService remoteAgentService: IRemoteAgentService, - @IExtensionGalleryService galleryService: IExtensionGalleryService, - @IConfigurationService configurationService: IConfigurationService, - @IProductService productService: IProductService, - @ILogService logService: ILogService - ) { -- const localExtensionManagementService = new ExtensionManagementChannelClient(sharedProcessService.getChannel('extensions')); -- -- this.localExtensionManagementServer = { extensionManagementService: localExtensionManagementService, authority: localExtensionManagementServerAuthority, label: localize('local', "Local") }; -- const remoteAgentConnection = remoteAgentService.getConnection(); -- if (remoteAgentConnection) { -- const extensionManagementService = new RemoteExtensionManagementChannelClient(remoteAgentConnection.getChannel('extensions'), this.localExtensionManagementServer.extensionManagementService, galleryService, logService, configurationService, productService); -- this.remoteExtensionManagementServer = { authority: remoteAgentConnection.remoteAuthority, extensionManagementService, label: localize('remote', "Remote") }; -- } -+ // const localExtensionManagementService = new ExtensionManagementChannelClient(sharedProcessService.getChannel('extensions')); -+ -+ this.localExtensionManagementServer = { extensionManagementService: localExtensionManagementService!, authority: localExtensionManagementServerAuthority, label: localize('remote', "Remote") }; -+ // const remoteAgentConnection = remoteAgentService.getConnection(); -+ // if (remoteAgentConnection) { -+ // const extensionManagementService = new RemoteExtensionManagementChannelClient(remoteAgentConnection.getChannel('extensions'), this.localExtensionManagementServer.extensionManagementService, galleryService, logService, configurationService, productService); -+ // this.remoteExtensionManagementServer = { authority: remoteAgentConnection.remoteAuthority, extensionManagementService, label: localize('remote', "Remote") }; -+ // } - } - - getExtensionManagementServer(location: URI): IExtensionManagementServer | null { -+ return this.localExtensionManagementServer; - if (location.scheme === Schemas.file) { - return this.localExtensionManagementServer; - } -diff --git a/src/vs/workbench/services/files/common/fileService.ts b/src/vs/workbench/services/files/common/fileService.ts -index a788aadc1f..bcffa2c60a 100644 ---- a/src/vs/workbench/services/files/common/fileService.ts -+++ b/src/vs/workbench/services/files/common/fileService.ts -@@ -859,7 +859,7 @@ export class FileService extends Disposable implements IFileService { - let posInFile = 0; - - let chunk: VSBuffer | null; -- while (chunk = readable.read()) { -+ while (chunk = await readable.read()) { - await this.doWriteBuffer(provider, handle, chunk, chunk.byteLength, posInFile, 0); - - posInFile += chunk.byteLength; -@@ -888,7 +888,7 @@ export class FileService extends Disposable implements IFileService { - if (bufferOrReadable instanceof VSBuffer) { - buffer = bufferOrReadable; - } else { -- buffer = readableToBuffer(bufferOrReadable); -+ buffer = await readableToBuffer(bufferOrReadable); - } - - return provider.writeFile(resource, buffer.buffer, { create: true, overwrite: true }); -diff --git a/src/vs/workbench/services/themes/common/fileIconThemeData.ts b/src/vs/workbench/services/themes/common/fileIconThemeData.ts -index 306d58f915..58c603ad3d 100644 ---- a/src/vs/workbench/services/themes/common/fileIconThemeData.ts -+++ b/src/vs/workbench/services/themes/common/fileIconThemeData.ts -@@ -331,7 +331,7 @@ function _processIconThemeDocument(id: string, iconThemeDocumentLocation: URI, i - let fonts = iconThemeDocument.fonts; - if (Array.isArray(fonts)) { - fonts.forEach(font => { -- let src = font.src.map(l => `url('${resolvePath(l.path)}') format('${l.format}')`).join(', '); -+ let src = font.src.map(l => `url('${require.withBase(resolvePath(l.path))}') format('${l.format}')`).join(', '); - cssRules.push(`@font-face { src: ${src}; font-family: '${font.id}'; font-weight: ${font.weight}; font-style: ${font.style}; }`); - }); - cssRules.push(`.show-file-icons .file-icon::before, .show-file-icons .folder-icon::before, .show-file-icons .rootfolder-icon::before { font-family: '${fonts[0].id}'; font-size: ${fonts[0].size || '150%'}}`); -@@ -342,7 +342,7 @@ function _processIconThemeDocument(id: string, iconThemeDocumentLocation: URI, i - let definition = iconThemeDocument.iconDefinitions[defId]; - if (definition) { - if (definition.iconPath) { -- cssRules.push(`${selectors.join(', ')} { content: ' '; background-image: url("${resolvePath(definition.iconPath)}"); }`); -+ cssRules.push(`${selectors.join(', ')} { content: ' '; background-image: url("${require.withBase(resolvePath(definition.iconPath))}"); }`); - } - if (definition.fontCharacter || definition.fontColor) { - let body = ''; + return this.webviewEndpoint ? this.webviewEndpoint + '/vscode-resource{{resource}}' : 'vscode-resource:{{resource}}'; diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts -index c28adc0ad9..56c86d7e39 100644 +index 4d5cf7bfbf..bc76a25106 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts -@@ -72,15 +72,15 @@ import { BrowserLifecycleService } from 'vs/platform/lifecycle/browser/lifecycle - import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; - import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; - import { DialogService } from 'vs/platform/dialogs/browser/dialogService'; --// import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; --// import { LocalizationsService } from 'vs/platform/localizations/electron-browser/localizationsService'; -+import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; -+import { LocalizationsService } from 'vs/platform/localizations/electron-browser/localizationsService'; - // import { ISharedProcessService, SharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; - // import { IProductService } from 'vs/platform/product/common/product'; - // import { ProductService } from 'vs/platform/product/node/productService'; - // import { IWindowsService } from 'vs/platform/windows/common/windows'; - // import { WindowsService } from 'vs/platform/windows/electron-browser/windowsService'; --// import { IUpdateService } from 'vs/platform/update/common/update'; --// import { UpdateService } from 'vs/platform/update/electron-browser/updateService'; -+import { IUpdateService } from 'vs/platform/update/common/update'; -+import { UpdateService } from 'vs/platform/update/electron-browser/updateService'; - // import { IIssueService } from 'vs/platform/issue/common/issue'; - // import { IssueService } from 'vs/platform/issue/electron-browser/issueService'; - // import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; -@@ -128,7 +128,7 @@ import 'vs/workbench/services/extensions/browser/extensionService'; - // import 'vs/workbench/services/contextmenu/electron-browser/contextmenuService'; - // import 'vs/workbench/services/extensions/node/multiExtensionManagement'; - import 'vs/workbench/services/label/common/labelService'; --// import 'vs/workbench/services/extensions/electron-browser/extensionManagementServerService'; -+import 'vs/workbench/services/extensions/electron-browser/extensionManagementServerService'; +@@ -126,7 +126,6 @@ import 'vs/workbench/services/extensionManagement/common/extensionEnablementServ // import 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl'; import 'vs/workbench/services/notification/common/notificationService'; // import 'vs/workbench/services/window/electron-browser/windowService'; -@@ -156,10 +156,10 @@ registerSingleton(IContextViewService, ContextViewService, true); - // registerSingleton(IExtensionGalleryService, ExtensionGalleryService, true); - // registerSingleton(IRequestService, RequestService, true); - registerSingleton(ILifecycleService, BrowserLifecycleService); --// registerSingleton(ILocalizationsService, LocalizationsService); -+registerSingleton(ILocalizationsService, LocalizationsService); - // registerSingleton(ISharedProcessService, SharedProcessService, true); - // registerSingleton(IWindowsService, WindowsService); --// registerSingleton(IUpdateService, UpdateService); -+registerSingleton(IUpdateService, UpdateService); - // registerSingleton(IIssueService, IssueService); - // registerSingleton(IWorkspacesService, WorkspacesService); - // registerSingleton(IMenubarService, MenubarService); -@@ -194,7 +194,7 @@ import 'vs/workbench/services/files/common/workspaceWatcher'; +-import 'vs/workbench/services/telemetry/browser/telemetryService'; + import 'vs/workbench/services/configurationResolver/browser/configurationResolverService'; + import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView'; + import { ContextMenuService } from 'vs/platform/contextview/browser/contextMenuService'; +@@ -195,7 +194,7 @@ import 'vs/workbench/services/files/common/workspaceWatcher'; import 'vs/workbench/contrib/telemetry/browser/telemetry.contribution'; // Localizations @@ -2091,25 +1024,3 @@ index c28adc0ad9..56c86d7e39 100644 // Preferences import 'vs/workbench/contrib/preferences/browser/preferences.contribution'; -@@ -260,9 +260,9 @@ registerSingleton(IWebviewService, WebviewService, true); - registerSingleton(IWebviewEditorService, WebviewEditorService, true); - - // Extensions Management --// import 'vs/workbench/contrib/extensions/electron-browser/extensions.contribution'; --// import 'vs/workbench/contrib/extensions/browser/extensionsQuickOpen'; --// import 'vs/workbench/contrib/extensions/electron-browser/extensionsViewlet'; -+import 'vs/workbench/contrib/extensions/electron-browser/extensions.contribution'; -+import 'vs/workbench/contrib/extensions/browser/extensionsQuickOpen'; -+import 'vs/workbench/contrib/extensions/electron-browser/extensionsViewlet'; - - // Output Panel - import 'vs/workbench/contrib/output/browser/output.contribution'; -@@ -318,7 +318,7 @@ import 'vs/workbench/contrib/format/browser/format.contribution'; - // import 'vs/workbench/contrib/feedback/browser/feedback.contribution'; - - // Update --// import 'vs/workbench/contrib/update/electron-browser/update.contribution'; -+import 'vs/workbench/contrib/update/electron-browser/update.contribution'; - - // Surveys - // import 'vs/workbench/contrib/surveys/electron-browser/nps.contribution'; diff --git a/src/api.ts b/src/api.ts index c7e882ea..cee4450b 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,35 +1,34 @@ -import * as vscode from "vscode"; - +import { createCSSRule } from "vs/base/browser/dom"; +import { Emitter, Event } from "vs/base/common/event"; +import { IDisposable } from "vs/base/common/lifecycle"; +import { URI } from "vs/base/common/uri"; +import { generateUuid } from "vs/base/common/uuid"; import { localize } from "vs/nls"; import { SyncActionDescriptor } from "vs/platform/actions/common/actions"; -import { Registry } from "vs/platform/registry/common/platform"; -import { IWorkbenchActionRegistry, Extensions as ActionExtensions} from "vs/workbench/common/actions"; import { CommandsRegistry, ICommandService } from "vs/platform/commands/common/commands"; -import { IStat, IWatchOptions, FileOverwriteOptions, FileDeleteOptions, FileOpenOptions, IFileChange, FileWriteOptions, FileSystemProviderCapabilities, IFileService, FileType, IFileSystemProvider } from "vs/platform/files/common/files"; -import { IStorageService } from "vs/platform/storage/common/storage"; +import { IConfigurationService } from "vs/platform/configuration/common/configuration"; +import { IContextMenuService } from "vs/platform/contextview/browser/contextView"; +import { FileDeleteOptions, FileOpenOptions, FileOverwriteOptions, FileSystemProviderCapabilities, FileType, FileWriteOptions, IFileChange, IFileService, IFileSystemProvider, IStat, IWatchOptions } from "vs/platform/files/common/files"; +import { IInstantiationService, ServiceIdentifier } from "vs/platform/instantiation/common/instantiation"; import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection"; import { INotificationService } from "vs/platform/notification/common/notification"; -import { Emitter, Event } from "vs/base/common/event"; -import * as extHostTypes from "vs/workbench/api/common/extHostTypes"; -import { ServiceIdentifier, IInstantiationService } from "vs/platform/instantiation/common/instantiation"; -import { URI } from "vs/base/common/uri"; -import { ITreeItem, ITreeViewDataProvider, IViewsRegistry, ITreeViewDescriptor, Extensions as ViewsExtensions, IViewContainersRegistry, TreeItemCollapsibleState } from "vs/workbench/common/views"; -import { CustomTreeViewPanel, CustomTreeView } from "vs/workbench/browser/parts/views/customView"; -import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor, ShowViewletAction } from "vs/workbench/browser/viewlet"; -import { IExtensionService } from "vs/workbench/services/extensions/common/extensions"; -import { ViewContainerViewlet } from "vs/workbench/browser/parts/views/viewsViewlet"; -import { IConfigurationService } from "vs/platform/configuration/common/configuration"; -import { IWorkbenchLayoutService } from "vs/workbench/services/layout/browser/layoutService"; +import { Registry } from "vs/platform/registry/common/platform"; +import { IStorageService } from "vs/platform/storage/common/storage"; import { ITelemetryService } from "vs/platform/telemetry/common/telemetry"; +import { IThemeService } from "vs/platform/theme/common/themeService"; import { IWorkspaceContextService } from "vs/platform/workspace/common/workspace"; +import * as extHostTypes from "vs/workbench/api/common/extHostTypes"; +import { CustomTreeView, CustomTreeViewPanel } from "vs/workbench/browser/parts/views/customView"; +import { ViewContainerViewlet } from "vs/workbench/browser/parts/views/viewsViewlet"; +import { Extensions as ViewletExtensions, ShowViewletAction, ViewletDescriptor, ViewletRegistry } from "vs/workbench/browser/viewlet"; +import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from "vs/workbench/common/actions"; +import { Extensions as ViewsExtensions, ITreeItem, ITreeViewDataProvider, ITreeViewDescriptor, IViewContainersRegistry, IViewsRegistry, TreeItemCollapsibleState } from "vs/workbench/common/views"; +import { IEditorGroupsService } from "vs/workbench/services/editor/common/editorGroupsService"; import { IEditorService } from "vs/workbench/services/editor/common/editorService"; -import { IThemeService } from "vs/platform/theme/common/themeService"; -import { IContextMenuService } from "vs/platform/contextview/browser/contextView"; +import { IExtensionService } from "vs/workbench/services/extensions/common/extensions"; +import { IWorkbenchLayoutService } from "vs/workbench/services/layout/browser/layoutService"; import { IViewletService } from "vs/workbench/services/viewlet/browser/viewlet"; -import { IEditorGroupsService } from "vs/workbench/services/editor/common/editorGroupsService"; -import { createCSSRule } from "vs/base/browser/dom"; -import { IDisposable } from "vs/base/common/lifecycle"; -import { generateUuid } from "vs/base/common/uuid"; +import * as vscode from "vscode"; /** * Client-side implementation of VS Code's API. diff --git a/src/channel.ts b/src/channel.ts index bfb2aecc..ee407a75 100644 --- a/src/channel.ts +++ b/src/channel.ts @@ -1,5 +1,4 @@ import * as path from "path"; - import { VSBuffer } from "vs/base/common/buffer"; import { Emitter, Event } from "vs/base/common/event"; import { IDisposable } from "vs/base/common/lifecycle"; @@ -9,18 +8,17 @@ import { transformOutgoingURIs } from "vs/base/common/uriIpc"; import { IServerChannel } from "vs/base/parts/ipc/common/ipc"; import { IDiagnosticInfo } from "vs/platform/diagnostics/common/diagnosticsService"; import { IEnvironmentService } from "vs/platform/environment/common/environment"; -import { IExtensionDescription, ExtensionIdentifier } from "vs/platform/extensions/common/extensions"; -import { FileDeleteOptions, FileOverwriteOptions, FileType, IStat, IWatchOptions, FileOpenOptions } from "vs/platform/files/common/files"; +import { ExtensionIdentifier, IExtensionDescription } from "vs/platform/extensions/common/extensions"; +import { FileDeleteOptions, FileOpenOptions, FileOverwriteOptions, FileType, IStat, IWatchOptions } from "vs/platform/files/common/files"; +import { DiskFileSystemProvider } from "vs/platform/files/node/diskFileSystemProvider"; import { ILogService } from "vs/platform/log/common/log"; import pkg from "vs/platform/product/node/package"; import product from "vs/platform/product/node/product"; import { IRemoteAgentEnvironment } from "vs/platform/remote/common/remoteAgentEnvironment"; import { ITelemetryService } from "vs/platform/telemetry/common/telemetry"; -import { ExtensionScanner, ExtensionScannerInput } from "vs/workbench/services/extensions/node/extensionPoints"; -import { DiskFileSystemProvider } from "vs/workbench/services/files/node/diskFileSystemProvider"; - import { getTranslations } from "vs/server/src/nls"; import { getUriTransformer } from "vs/server/src/util"; +import { ExtensionScanner, ExtensionScannerInput } from "vs/workbench/services/extensions/node/extensionPoints"; /** * Extend the file provider to allow unwatching. @@ -205,7 +203,7 @@ export class ExtensionEnvironmentChannel implements IServerChannel { appSettingsHome: this.environment.appSettingsHome, settingsPath: this.environment.machineSettingsHome, logsPath: URI.file(this.environment.logsPath), - extensionsPath: URI.file(this.environment.extensionsPath), + extensionsPath: URI.file(this.environment.extensionsPath!), extensionHostLogsPath: URI.file(path.join(this.environment.logsPath, "extension-host")), globalStorageHome: URI.file(this.environment.globalStorageHome), userHome: URI.file(this.environment.userHome), @@ -237,7 +235,7 @@ export class ExtensionEnvironmentChannel implements IServerChannel { }; const scanInstalled = async (): Promise => { - return scanMultiple(false, true, [this.environment.extensionsPath, ...this.environment.extraExtensionPaths]); + return scanMultiple(false, true, [this.environment.extensionsPath!, ...this.environment.extraExtensionPaths]); }; return Promise.all([scanBuiltin(), scanInstalled()]).then((allExtensions) => { diff --git a/src/cli.ts b/src/cli.ts index 3ea83e8e..54c1c7e1 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -1,27 +1,16 @@ import * as cp from "child_process"; import * as os from "os"; - import { main as vsCli } from "vs/code/node/cliProcessMain"; import { validatePaths } from "vs/code/node/paths"; -import { parseMainProcessArgv } from "vs/platform/environment/node/argvHelper"; -import { buildHelpMessage, buildVersionMessage, options } from "vs/platform/environment/node/argv"; import { ParsedArgs } from "vs/platform/environment/common/environment"; +import { buildHelpMessage, buildVersionMessage, Option as VsOption, options as vsOptions } from "vs/platform/environment/node/argv"; +import { parseMainProcessArgv } from "vs/platform/environment/node/argvHelper"; import pkg from "vs/platform/product/node/package"; import product from "vs/platform/product/node/product"; - import { ipcMain } from "vs/server/src/ipc"; - -product.extensionsGallery = { - serviceUrl: process.env.SERVICE_URL || "https://v1.extapi.coder.com", - itemUrl: process.env.ITEM_URL || "", - controlUrl: "", - recommendationsUrl: "", - ...(product.extensionsGallery || {}), -}; - +import { enableCustomMarketplace } from "vs/server/src/marketplace"; import { MainServer } from "vs/server/src/server"; -import { enableExtensionTars } from "vs/server/src/tar"; -import { AuthType, buildAllowedMessage, generateCertificate, generatePassword, localRequire, open, unpackExecutables } from "vs/server/src/util"; +import { AuthType, buildAllowedMessage, enumToArray, generateCertificate, generatePassword, localRequire, open, unpackExecutables } from "vs/server/src/util"; const { logger } = localRequire("@coder/logger/out/index"); @@ -30,15 +19,19 @@ interface Args extends ParsedArgs { "base-path"?: string; cert?: string; "cert-key"?: string; - "extra-builtin-extensions-dir"?: string; - "extra-extensions-dir"?: string; host?: string; open?: string; port?: string; socket?: string; } +// @ts-ignore: Force `keyof Args` to work. +interface Option extends VsOption { + id: keyof Args; +} + const getArgs = (): Args => { + const options = vsOptions as Option[]; // The last item is _ which is like -- so our options need to come before it. const last = options.pop()!; @@ -78,13 +71,7 @@ const getArgs = (): Args => { options.push(last); - const args = validatePaths(parseMainProcessArgv(process.argv)) as Args; - ["extra-extensions-dir", "extra-builtin-extensions-dir"].forEach((key) => { - if (typeof args[key] === "string") { - args[key] = [args[key]]; - } - }); - return args; + return validatePaths(parseMainProcessArgv(process.argv)); }; const startVscode = async (): Promise => { @@ -100,7 +87,7 @@ const startVscode = async (): Promise => { password: process.env.PASSWORD, }; - if (options.auth && Object.keys(AuthType).filter((k) => AuthType[k] === options.auth).length === 0) { + if (options.auth && enumToArray(AuthType).filter((t) => t === options.auth).length === 0) { throw new Error(`'${options.auth}' is not a valid authentication type.`); } else if (options.auth && !options.password) { options.password = await generatePassword(); @@ -116,7 +103,7 @@ const startVscode = async (): Promise => { options.certKey = certKey; } - enableExtensionTars(); + enableCustomMarketplace(); const server = new MainServer({ ...options, @@ -180,7 +167,7 @@ const startCli = (): boolean | Promise => { }; if (shouldSpawnCliProcess()) { - enableExtensionTars(); + enableCustomMarketplace(); return vsCli(args); } diff --git a/src/client.ts b/src/client.ts index 0df27d8a..505392d1 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,8 +1,29 @@ +import { registerSingleton } from "vs/platform/instantiation/common/extensions"; import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection"; +import { ITelemetryService } from "vs/platform/telemetry/common/telemetry"; +import { ILocalizationsService } from "vs/platform/localizations/common/localizations"; +import { LocalizationsService } from "vs/platform/localizations/electron-browser/localizationsService"; +import { IUpdateService } from "vs/platform/update/common/update"; +import { UpdateService } from "vs/platform/update/electron-browser/updateService"; +import { TelemetryChannelClient } from "vs/server/src/telemetry"; +import { IRemoteAgentService } from "vs/workbench/services/remote/common/remoteAgentService"; -import { coderApi, vscodeApi } from "vs/server/src/api"; +class TelemetryService extends TelemetryChannelClient { + public constructor( + @IRemoteAgentService remoteAgentService: IRemoteAgentService, + ) { + super(remoteAgentService.getConnection()!.getChannel("telemetry")); + } +} + +registerSingleton(ILocalizationsService, LocalizationsService); +registerSingleton(IUpdateService, UpdateService); +registerSingleton(ITelemetryService, TelemetryService); + +import "vs/workbench/contrib/update/electron-browser/update.contribution"; import "vs/css!./media/firefox"; +import { coderApi, vscodeApi } from "vs/server/src/api"; /** * This is called by vs/workbench/browser/web.main.ts after the workbench has @@ -13,7 +34,7 @@ export const initialize = async (services: ServiceCollection): Promise => target.ide = coderApi(services); target.vscode = vscodeApi(services); - const event = new CustomEvent('ide-ready'); + const event = new CustomEvent("ide-ready"); (event as any).ide = target.ide; (event as any).vscode = target.vscode; window.dispatchEvent(event); diff --git a/src/connection.ts b/src/connection.ts index c5d17e10..15bf1c01 100644 --- a/src/connection.ts +++ b/src/connection.ts @@ -1,5 +1,4 @@ import * as cp from "child_process"; - import { getPathFromAmdModule } from "vs/base/common/amd"; import { VSBuffer } from "vs/base/common/buffer"; import { Emitter } from "vs/base/common/event"; @@ -7,11 +6,10 @@ import { ISocket } from "vs/base/parts/ipc/common/ipc.net"; import { NodeSocket } from "vs/base/parts/ipc/node/ipc.net"; import { IEnvironmentService } from "vs/platform/environment/common/environment"; import { ILogService } from "vs/platform/log/common/log"; -import { IExtHostReadyMessage } from "vs/workbench/services/extensions/common/extensionHostProtocol"; - import { getNlsConfiguration } from "vs/server/src/nls"; import { Protocol } from "vs/server/src/protocol"; import { uriTransformerPath } from "vs/server/src/util"; +import { IExtHostReadyMessage } from "vs/workbench/services/extensions/common/extensionHostProtocol"; export abstract class Connection { protected readonly _onClose = new Emitter(); @@ -126,8 +124,8 @@ export class ExtensionHostConnection extends Connection { proc.stderr.setEncoding("utf8").on("data", (d) => this.log.error("Extension host stderr", d)); proc.on("message", (event) => { if (event && event.type === "__$console") { - const severity = this.log[event.severity] ? event.severity : "info"; - this.log[severity]("Extension host", event.arguments); + const severity = (this.log)[event.severity] ? event.severity : "info"; + (this.log)[severity]("Extension host", event.arguments); } }); diff --git a/src/insights.ts b/src/insights.ts index 031bd3cb..ee841620 100644 --- a/src/insights.ts +++ b/src/insights.ts @@ -1,8 +1,7 @@ +import * as appInsights from "applicationinsights"; import * as https from "https"; import * as os from "os"; -import * as appInsights from "applicationinsights"; - export class TelemetryClient implements appInsights.TelemetryClient { public config: any = {}; diff --git a/src/ipc.ts b/src/ipc.ts index 48e85fe4..da188234 100644 --- a/src/ipc.ts +++ b/src/ipc.ts @@ -1,5 +1,4 @@ import * as cp from "child_process"; - import { Emitter } from "vs/base/common/event"; enum ControlMessage { diff --git a/src/tar.ts b/src/marketplace.ts similarity index 91% rename from src/tar.ts rename to src/marketplace.ts index 73156f64..0b63eea1 100644 --- a/src/tar.ts +++ b/src/marketplace.ts @@ -2,11 +2,11 @@ import * as fs from "fs"; import * as path from "path"; import * as tarStream from "tar-stream"; import * as util from "util"; - -import * as nls from "vs/nls"; -import * as vszip from "vs/base/node/zip"; import { CancellationToken } from "vs/base/common/cancellation"; import { mkdirp } from "vs/base/node/pfs"; +import * as vszip from "vs/base/node/zip"; +import * as nls from "vs/nls"; +import product from "vs/platform/product/node/product"; // We will be overriding these, so keep a reference to the original. const vszipExtract = vszip.extract; @@ -154,10 +154,18 @@ const extractTar = async (tarPath: string, targetPath: string, options: IExtract }; /** - * Override original functionality so we can use extensions that are in a tar in - * addition to zips. + * Override original functionality so we can use a custom marketplace with + * either tars or zips. */ -export const enableExtensionTars = (): void => { +export const enableCustomMarketplace = (): void => { + (product).extensionsGallery = { // Use `any` to override readonly. + serviceUrl: process.env.SERVICE_URL || "https://v1.extapi.coder.com", + itemUrl: process.env.ITEM_URL || "", + controlUrl: "", + recommendationsUrl: "", + ...(product.extensionsGallery || {}), + }; + const target = vszip as typeof vszip; target.zip = tar; target.extract = extract; diff --git a/src/nls.ts b/src/nls.ts index e9ef4a8c..30922502 100644 --- a/src/nls.ts +++ b/src/nls.ts @@ -1,7 +1,6 @@ -import * as path from "path"; import * as fs from "fs"; +import * as path from "path"; import * as util from "util"; - import { getPathFromAmdModule } from "vs/base/common/amd"; import * as lp from "vs/base/node/languagePacks"; import product from "vs/platform/product/node/product"; diff --git a/src/protocol.ts b/src/protocol.ts index 138b9c3a..fde6662a 100644 --- a/src/protocol.ts +++ b/src/protocol.ts @@ -1,8 +1,7 @@ import * as net from "net"; - import { VSBuffer } from "vs/base/common/buffer"; -import { NodeSocket, WebSocketNodeSocket } from "vs/base/parts/ipc/node/ipc.net"; import { PersistentProtocol } from "vs/base/parts/ipc/common/ipc.net"; +import { NodeSocket, WebSocketNodeSocket } from "vs/base/parts/ipc/node/ipc.net"; import { AuthRequest, ConnectionTypeRequest, HandshakeMessage } from "vs/platform/remote/common/remoteAgentConnection"; export interface SocketOptions { diff --git a/src/server.ts b/src/server.ts index 4e7f4a4d..fc8cc1c4 100644 --- a/src/server.ts +++ b/src/server.ts @@ -4,31 +4,34 @@ import * as http from "http"; import * as https from "https"; import * as net from "net"; import * as path from "path"; +import * as querystring from "querystring"; import * as tls from "tls"; -import * as util from "util"; import * as url from "url"; -import * as querystring from "querystring"; - +import * as util from "util"; import { Emitter } from "vs/base/common/event"; import { sanitizeFilePath } from "vs/base/common/extpath"; -import { UriComponents, URI } from "vs/base/common/uri"; +import { Schemas } from "vs/base/common/network"; +import { URI, UriComponents } from "vs/base/common/uri"; import { generateUuid } from "vs/base/common/uuid"; import { getMachineId } from 'vs/base/node/id'; import { NLSConfiguration } from "vs/base/node/languagePacks"; import { mkdirp, rimraf } from "vs/base/node/pfs"; -import { IPCServer, ClientConnectionEvent, StaticRouter } from "vs/base/parts/ipc/common/ipc"; +import { ClientConnectionEvent, IPCServer, StaticRouter } from "vs/base/parts/ipc/common/ipc"; import { LogsDataCleaner } from "vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner"; import { IConfigurationService } from "vs/platform/configuration/common/configuration"; import { ConfigurationService } from "vs/platform/configuration/node/configurationService"; +import { ExtensionHostDebugBroadcastChannel } from "vs/platform/debug/common/extensionHostDebugIpc"; import { IDialogService } from "vs/platform/dialogs/common/dialogs"; import { DialogChannelClient } from "vs/platform/dialogs/node/dialogIpc"; import { IEnvironmentService, ParsedArgs } from "vs/platform/environment/common/environment"; import { EnvironmentService } from "vs/platform/environment/node/environmentService"; -import { IExtensionManagementService, IExtensionGalleryService } from "vs/platform/extensionManagement/common/extensionManagement"; -import { ExtensionGalleryChannel } from "vs/platform/extensionManagement/node/extensionGalleryIpc"; -import { ExtensionGalleryService } from "vs/platform/extensionManagement/node/extensionGalleryService"; -import { ExtensionManagementChannel } from "vs/platform/extensionManagement/node/extensionManagementIpc"; +import { ExtensionGalleryService } from "vs/platform/extensionManagement/common/extensionGalleryService"; +import { IExtensionGalleryService, IExtensionManagementService } from "vs/platform/extensionManagement/common/extensionManagement"; +import { ExtensionManagementChannel } from "vs/platform/extensionManagement/common/extensionManagementIpc"; import { ExtensionManagementService } from "vs/platform/extensionManagement/node/extensionManagementService"; +import { IFileService } from "vs/platform/files/common/files"; +import { FileService } from "vs/platform/files/common/fileService"; +import { DiskFileSystemProvider } from "vs/platform/files/node/diskFileSystemProvider"; import { SyncDescriptor } from "vs/platform/instantiation/common/descriptors"; import { InstantiationService } from "vs/platform/instantiation/common/instantiationService"; import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection"; @@ -38,31 +41,32 @@ import { LocalizationsChannel } from "vs/platform/localizations/node/localizatio import { getLogLevel, ILogService } from "vs/platform/log/common/log"; import { LogLevelSetterChannel } from "vs/platform/log/common/logIpc"; import { SpdLogService } from "vs/platform/log/node/spdlogService"; -import { IProductConfiguration } from "vs/platform/product/common/product"; +import { IProductConfiguration, IProductService } from "vs/platform/product/common/product"; import pkg from "vs/platform/product/node/package"; import product from "vs/platform/product/node/product"; +import { ProductService } from "vs/platform/product/node/productService"; import { ConnectionType, ConnectionTypeRequest } from "vs/platform/remote/common/remoteAgentConnection"; import { REMOTE_FILE_SYSTEM_CHANNEL_NAME } from "vs/platform/remote/common/remoteAgentFileSystemChannel"; -import { IRequestService } from "vs/platform/request/node/request"; +import { IRequestService } from "vs/platform/request/common/request"; +import { RequestChannel } from "vs/platform/request/common/requestIpc"; import { RequestService } from "vs/platform/request/node/requestService"; import ErrorTelemetry from "vs/platform/telemetry/browser/errorTelemetry"; import { ITelemetryService } from "vs/platform/telemetry/common/telemetry"; -import { NullTelemetryService, LogAppender, combinedAppender } from "vs/platform/telemetry/common/telemetryUtils"; -import { TelemetryService, ITelemetryServiceConfig } from "vs/platform/telemetry/common/telemetryService"; +import { ITelemetryServiceConfig, TelemetryService } from "vs/platform/telemetry/common/telemetryService"; +import { combinedAppender, LogAppender, NullTelemetryService } from "vs/platform/telemetry/common/telemetryUtils"; import { AppInsightsAppender } from "vs/platform/telemetry/node/appInsightsAppender"; import { resolveCommonProperties } from "vs/platform/telemetry/node/commonProperties"; -import { RemoteExtensionLogFileName } from "vs/workbench/services/remote/common/remoteAgentService"; -import { TelemetryChannel } from "vs/platform/telemetry/node/telemetryIpc"; import { UpdateChannel } from "vs/platform/update/node/updateIpc"; -import { IWorkbenchConstructionOptions } from "vs/workbench/workbench.web.api"; - -import { Connection, ManagementConnection, ExtensionHostConnection } from "vs/server/src/connection"; -import { ExtensionEnvironmentChannel, FileProviderChannel , } from "vs/server/src/channel"; +import { ExtensionEnvironmentChannel, FileProviderChannel } from "vs/server/src/channel"; +import { Connection, ExtensionHostConnection, ManagementConnection } from "vs/server/src/connection"; import { TelemetryClient } from "vs/server/src/insights"; -import { getNlsConfiguration, getLocaleFromConfig } from "vs/server/src/nls"; +import { getLocaleFromConfig, getNlsConfiguration } from "vs/server/src/nls"; import { Protocol } from "vs/server/src/protocol"; +import { TelemetryChannel } from "vs/server/src/telemetry"; import { UpdateService } from "vs/server/src/update"; import { AuthType, getMediaMime, getUriTransformer, localRequire, tmpdir } from "vs/server/src/util"; +import { RemoteExtensionLogFileName } from "vs/workbench/services/remote/common/remoteAgentService"; +import { IWorkbenchConstructionOptions } from "vs/workbench/workbench.web.api"; export enum HttpCode { Ok = 200, @@ -192,9 +196,9 @@ export abstract class Server { try { const payload = await this.preHandleRequest(request); response.writeHead(payload.redirect ? HttpCode.Redirect : payload.code || HttpCode.Ok, { - "Cache-Control": "max-age=86400", // TODO: ETag? "Content-Type": getMediaMime(payload.filePath), ...(payload.redirect ? { Location: this.withBase(request, payload.redirect) } : {}), + ...(request.headers["service-worker"] ? { "Service-Worker-Allowed": this.options.basePath + "/" } : {}), ...payload.headers, }); response.end(payload.content); @@ -438,7 +442,7 @@ export class MainServer extends Server { ): Promise { switch (base) { case "/": return this.getRoot(request, parsedUrl); - case "/resources": return this.getResource(requestPath); + case "/vscode-resources": return this.getResource(requestPath); case "/webview": if (requestPath.indexOf("/vscode-resource") === 0) { return this.getResource(requestPath.replace(/^\/vscode-resource/, "")); @@ -490,15 +494,19 @@ export class MainServer extends Server { NLS_CONFIGURATION: await getNlsConfiguration(locale, environment.userDataPath), }; - Object.keys(options).forEach((key) => { - content = content.replace(`"{{${key}}}"`, `'${JSON.stringify(options[key])}'`); - }); + for (const key in options) { + content = content.replace(`"{{${key}}}"`, `'${JSON.stringify(options[key as keyof Options])}'`); + } content = content.replace('{{WEBVIEW_ENDPOINT}}', webviewEndpoint); return { content, filePath }; } private async connect(message: ConnectionTypeRequest, protocol: Protocol): Promise { + if (product.commit && message.commit !== product.commit) { + throw new Error(`Version mismatch (${message.commit} instead of ${product.commit})`); + } + switch (message.desiredConnectionType) { case ConnectionType.ExtensionHost: case ConnectionType.Management: @@ -552,16 +560,25 @@ export class MainServer extends Server { } private async initializeServices(args: ParsedArgs): Promise { - const router = new StaticRouter((ctx: any) => ctx.clientId === "renderer"); const environmentService = new EnvironmentService(args, process.execPath); const logService = new SpdLogService(RemoteExtensionLogFileName, environmentService.logsPath, getLogLevel(environmentService)); + const fileService = new FileService(logService); + fileService.registerProvider(Schemas.file, new DiskFileSystemProvider(logService)); + this.ipc.registerChannel("loglevel", new LogLevelSetterChannel(logService)); + this.ipc.registerChannel(ExtensionHostDebugBroadcastChannel.ChannelName, new ExtensionHostDebugBroadcastChannel()); + const router = new StaticRouter((ctx: any) => ctx.clientId === "renderer"); this.services.set(ILogService, logService); this.services.set(IEnvironmentService, environmentService); this.services.set(IConfigurationService, new SyncDescriptor(ConfigurationService, [environmentService.machineSettingsResource])); this.services.set(IRequestService, new SyncDescriptor(RequestService)); + this.services.set(IFileService, fileService); + this.services.set(IProductService, new SyncDescriptor(ProductService)); + this.services.set(IDialogService, new DialogChannelClient(this.ipc.getChannel("dialog", router))); this.services.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService)); + this.services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService)); + if (!environmentService.args["disable-telemetry"]) { this.services.set(ITelemetryService, new SyncDescriptor(TelemetryService, [{ appender: combinedAppender( @@ -582,8 +599,6 @@ export class MainServer extends Server { } else { this.services.set(ITelemetryService, NullTelemetryService); } - this.services.set(IDialogService, new DialogChannelClient(this.ipc.getChannel("dialog", router))); - this.services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService)); await new Promise((resolve) => { const instantiationService = new InstantiationService(this.services); @@ -592,19 +607,23 @@ export class MainServer extends Server { this.ipc.registerChannel("localizations", new LocalizationsChannel(localizationService)); instantiationService.invokeFunction(() => { instantiationService.createInstance(LogsDataCleaner); - this.ipc.registerChannel(REMOTE_FILE_SYSTEM_CHANNEL_NAME, new FileProviderChannel(environmentService, logService)); - const telemetryService = this.services.get(ITelemetryService) as ITelemetryService; - this.ipc.registerChannel("remoteextensionsenvironment", new ExtensionEnvironmentChannel(environmentService, logService, telemetryService)); + const extensionsService = this.services.get(IExtensionManagementService) as IExtensionManagementService; + const telemetryService = this.services.get(ITelemetryService) as ITelemetryService; + const extensionsChannel = new ExtensionManagementChannel(extensionsService, (context) => getUriTransformer(context.remoteAuthority)); - this.ipc.registerChannel("extensions", extensionsChannel); - const galleryService = this.services.get(IExtensionGalleryService) as IExtensionGalleryService; - const galleryChannel = new ExtensionGalleryChannel(galleryService); - this.ipc.registerChannel("gallery", galleryChannel); + const extensionsEnvironmentChannel = new ExtensionEnvironmentChannel(environmentService, logService, telemetryService); + const fileChannel = new FileProviderChannel(environmentService, logService); + const requestChannel = new RequestChannel(this.services.get(IRequestService) as IRequestService); const telemetryChannel = new TelemetryChannel(telemetryService); - this.ipc.registerChannel("telemetry", telemetryChannel); const updateChannel = new UpdateChannel(instantiationService.createInstance(UpdateService)); + + this.ipc.registerChannel("extensions", extensionsChannel); + this.ipc.registerChannel("remoteextensionsenvironment", extensionsEnvironmentChannel); + this.ipc.registerChannel("request", requestChannel); + this.ipc.registerChannel("telemetry", telemetryChannel); this.ipc.registerChannel("update", updateChannel); + this.ipc.registerChannel(REMOTE_FILE_SYSTEM_CHANNEL_NAME, fileChannel); resolve(new ErrorTelemetry(telemetryService)); }); }); diff --git a/src/telemetry.ts b/src/telemetry.ts new file mode 100644 index 00000000..28adaed5 --- /dev/null +++ b/src/telemetry.ts @@ -0,0 +1,49 @@ +import { ITelemetryData } from "vs/base/common/actions"; +import { Event } from "vs/base/common/event"; +import { IChannel, IServerChannel } from "vs/base/parts/ipc/common/ipc"; +import { ClassifiedEvent, GDPRClassification, StrictPropertyCheck } from "vs/platform/telemetry/common/gdprTypings"; +import { ITelemetryInfo, ITelemetryService } from "vs/platform/telemetry/common/telemetry"; + +export class TelemetryChannel implements IServerChannel { + constructor(private service: ITelemetryService) {} + + listen(_: unknown, event: string): Event { + throw new Error(`Invalid listen ${event}`); + } + + call(_: unknown, command: string, args?: any): Promise { + switch (command) { + case "publicLog": return this.service.publicLog(args[0], args[1], args[2]); + case "publicLog2": return this.service.publicLog2(args[0], args[1], args[2]); + case "setEnabled": return Promise.resolve(this.service.setEnabled(args[0])); + case "getTelemetryInfo": return this.service.getTelemetryInfo(); + } + throw new Error(`Invalid call ${command}`); + } +} + +export class TelemetryChannelClient implements ITelemetryService { + _serviceBrand: any; + + constructor(private readonly channel: IChannel) {} + + public publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): Promise { + return this.channel.call("publicLog", [eventName, data, anonymizeFilePaths]); + } + + public publicLog2 = never, T extends GDPRClassification = never>(eventName: string, data?: StrictPropertyCheck, anonymizeFilePaths?: boolean): Promise { + return this.channel.call("publicLog2", [eventName, data, anonymizeFilePaths]); + } + + public setEnabled(value: boolean): void { + this.channel.call("setEnable", [value]); + } + + public getTelemetryInfo(): Promise { + return this.channel.call("getTelemetryInfo"); + } + + public get isOptedIn(): boolean { + return true; + } +} diff --git a/src/update.ts b/src/update.ts index 0a62ddb9..cc2dcbed 100644 --- a/src/update.ts +++ b/src/update.ts @@ -1,23 +1,24 @@ import * as cp from "child_process"; import * as os from "os"; import * as path from "path"; +import { Stream } from "stream"; import * as util from "util"; -import * as zlib from 'zlib'; - +import { toVSBufferReadableStream } from "vs/base/common/buffer"; import { CancellationToken } from "vs/base/common/cancellation"; +import { URI } from "vs/base/common/uri"; import * as pfs from "vs/base/node/pfs"; -import { asJson, download } from "vs/base/node/request"; import { IConfigurationService } from "vs/platform/configuration/common/configuration"; import { IEnvironmentService } from "vs/platform/environment/common/environment"; +import { IFileService } from "vs/platform/files/common/files"; import { ILogService } from "vs/platform/log/common/log"; import pkg from "vs/platform/product/node/package"; -import { IRequestService } from "vs/platform/request/node/request"; -import { State, UpdateType, StateType, AvailableForDownload } from "vs/platform/update/common/update"; +import { asJson, IRequestService } from "vs/platform/request/common/request"; +import { AvailableForDownload, State, StateType, UpdateType } from "vs/platform/update/common/update"; import { AbstractUpdateService } from "vs/platform/update/electron-main/abstractUpdateService"; - import { ipcMain } from "vs/server/src/ipc"; +import { extract } from "vs/server/src/marketplace"; import { tmpdir } from "vs/server/src/util"; -import { extract } from "vs/server/src/tar"; +import * as zlib from "zlib"; interface IUpdate { name: string; @@ -30,7 +31,8 @@ export class UpdateService extends AbstractUpdateService { @IConfigurationService configurationService: IConfigurationService, @IEnvironmentService environmentService: IEnvironmentService, @IRequestService requestService: IRequestService, - @ILogService logService: ILogService + @ILogService logService: ILogService, + @IFileService private readonly fileService: IFileService, ) { super(null, configurationService, environmentService, requestService, logService); } @@ -92,10 +94,13 @@ export class UpdateService extends AbstractUpdateService { const context = await this.requestService.request({ url }, CancellationToken.None); // Decompress the gzip as we download. If the gzip encoding is set then // the request service already does this. + // HACK: This uses knowledge of the internals of the request service. if (target !== "darwin" && context.res.headers["content-encoding"] !== "gzip") { - context.stream = context.stream.pipe(zlib.createGunzip()); + const stream = (context.res as any as Stream); + stream.removeAllListeners(); + context.stream = toVSBufferReadableStream(stream.pipe(zlib.createGunzip())); } - await download(downloadPath, context); + await this.fileService.writeFile(URI.file(downloadPath), context.stream); await extract(downloadPath, extractPath, undefined, CancellationToken.None); const newBinary = path.join(extractPath, releaseName, "code-server"); if (!pfs.exists(newBinary)) { diff --git a/src/upload.ts b/src/upload.ts index bb732f35..1ffba04b 100644 --- a/src/upload.ts +++ b/src/upload.ts @@ -1,18 +1,17 @@ -import { generateUuid } from "vs/base/common/uuid"; import { DesktopDragAndDropData } from "vs/base/browser/ui/list/listView"; -import { VSBuffer, VSBufferReadable } from "vs/base/common/buffer"; -import { Emitter, Event } from "vs/base/common/event"; +import { VSBuffer, VSBufferReadableStream } from "vs/base/common/buffer"; import { Disposable } from "vs/base/common/lifecycle"; import * as path from "vs/base/common/path"; import { URI } from "vs/base/common/uri"; +import { generateUuid } from "vs/base/common/uuid"; import { IFileService } from "vs/platform/files/common/files"; -import { createDecorator, ServiceIdentifier, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { createDecorator, IInstantiationService, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; import { INotificationService, Severity } from "vs/platform/notification/common/notification"; -import { IProgress, IProgressStep, IProgressService, ProgressLocation } from "vs/platform/progress/common/progress"; +import { IProgress, IProgressService, IProgressStep, ProgressLocation } from "vs/platform/progress/common/progress"; +import { IWindowsService } from "vs/platform/windows/common/windows"; +import { IWorkspaceContextService } from "vs/platform/workspace/common/workspace"; import { ExplorerItem } from "vs/workbench/contrib/files/common/explorerModel"; import { IEditorGroup } from "vs/workbench/services/editor/common/editorGroupsService"; -import { IWorkspaceContextService } from "vs/platform/workspace/common/workspace"; -import { IWindowsService } from "vs/platform/windows/common/windows"; import { IEditorService } from "vs/workbench/services/editor/common/editorService"; export const IUploadService = createDecorator("uploadService"); @@ -208,20 +207,15 @@ class Upload { ), }); const reader = new Reader(file); - reader.onData((data) => { - if (data && data.length > 0) { + reader.on("data", (data) => { + if (data && data.byteLength > 0) { this.uploaded += data.byteLength; } }); - reader.onAbort(() => { - const remaining = file.size - reader.offset; - if (remaining > 0) { - this.uploaded += remaining; - } - }); this.uploadingFiles.set(filePath, reader); await this.fileService.writeFile(tempUri, reader); if (reader.aborted) { + this.uploaded += (file.size - reader.offset); await this.fileService.del(tempUri); } else { await this.fileService.move(tempUri, uri, true); @@ -292,17 +286,14 @@ class Upload { } } -class Reader implements VSBufferReadable { +class Reader implements VSBufferReadableStream { private _offset = 0; private readonly size = 32000; // ~32kb max while reading in the file. - private readonly _onData = new Emitter(); - public readonly onData: Event = this._onData.event; - private _aborted = false; - private readonly _onAbort = new Emitter(); - public readonly onAbort: Event = this._onAbort.event; - private readonly reader = new FileReader(); + private paused = true; + private buffer?: VSBuffer; + private callbacks = new Map void>>(); public constructor(private readonly file: File) { this.reader.addEventListener("load", this.onLoad); @@ -311,35 +302,71 @@ class Reader implements VSBufferReadable { public get offset(): number { return this._offset; } public get aborted(): boolean { return this._aborted; } + public on(event: "data" | "error" | "end", callback: (...args:any[]) => void): void { + if (!this.callbacks.has(event)) { + this.callbacks.set(event, []); + } + this.callbacks.get(event)!.push(callback); + if (this.aborted) { + return this.emit("error", new Error("stream has been aborted")); + } else if (this.done) { + return this.emit("error", new Error("stream has ended")); + } else if (event === "end") { // Once this is being listened to we can safely start outputting data. + this.resume(); + } + } + public abort = (): void => { this._aborted = true; this.reader.abort(); this.reader.removeEventListener("load", this.onLoad); - this._onAbort.fire(); + this.emit("end"); + } + + public pause(): void { + this.paused = true; } - public read = async (): Promise => { - return new Promise((resolve) => { - const disposables = [ - this.onAbort(() => { - disposables.forEach((d) => d.dispose()); - resolve(null); - }), - this.onData((data) => { - disposables.forEach((d) => d.dispose()); - resolve(data && VSBuffer.wrap(data)); - }), - ]; - if (this.aborted || this.offset >= this.file.size) { - return this._onData.fire(null); + public resume(): void { + if (this.paused) { + this.paused = false; + this.readNextChunk(); + } + } + + public destroy(): void { + this.abort(); + } + + private onLoad = (): void => { + this.buffer = VSBuffer.wrap(new Uint8Array(this.reader.result as ArrayBuffer)); + if (!this.paused) { + this.readNextChunk(); + } + } + + private readNextChunk(): void { + if (this.buffer) { + this._offset += this.buffer.byteLength; + this.emit("data", this.buffer); + this.buffer = undefined; + } + if (!this.paused) { // Could be paused during the data event. + if (this.done) { + this.emit("end"); + } else { + this.reader.readAsArrayBuffer(this.file.slice(this.offset, this.offset + this.size)); } - const slice = this.file.slice(this.offset, this.offset + this.size); - this._offset += this.size; - this.reader.readAsArrayBuffer(slice); - }); + } + } + + private emit(event: "data" | "error" | "end", ...args: any[]): void { + if (this.callbacks.has(event)) { + this.callbacks.get(event)!.forEach((cb) => cb(...args)); + } } - private onLoad = () => { - this._onData.fire(new Uint8Array(this.reader.result as ArrayBuffer)); + private get done(): boolean { + return this.offset >= this.file.size; } } diff --git a/src/util.ts b/src/util.ts index bda487ff..9e8a6ffd 100644 --- a/src/util.ts +++ b/src/util.ts @@ -63,12 +63,12 @@ export const generatePassword = async (length: number = 24): Promise => }; export const getMediaMime = (filePath?: string): string => { - return filePath && (vsGetMediaMime(filePath) || { + return filePath && (vsGetMediaMime(filePath) || (<{[index: string]: string}>{ ".css": "text/css", ".html": "text/html", ".js": "text/javascript", ".json": "application/json", - }[extname(filePath)]) || "text/plain"; + })[extname(filePath)]) || "text/plain"; }; export const isWsl = async (): Promise => { @@ -113,8 +113,16 @@ export const unpackExecutables = async (): Promise => { } }; -export const buildAllowedMessage = (t: typeof AuthType): string => { - const values = Object.keys(t).map((k) => t[k]); +export const enumToArray = (t: any): string[] => { + const values = []; + for (const k in t) { + values.push(t[k]); + } + return values; +}; + +export const buildAllowedMessage = (t: any): string => { + const values = enumToArray(t); return `Allowed value${values.length === 1 ? " is" : "s are"} ${values.map((t) => `'${t}'`).join(",")}`; }; -- GitLab