d574012871
When using a query parameter without a scheme, the scheme defaults to `file`. This results in the files in the explorer being technically different from the file picker files because they are file:// instead of vscode-remote://, causing the same file to open twice and causing numerous issues. Normally the file explorer wouldn't even load at all in this case but we provide a file service for file:// URLs as a failsafe for certain files that wouldn't load correctly in the past. These files load fine now using the vscode-remote scheme, so I'm also removing that service. Related: #1351. Fixes #1294.
997 lines
51 KiB
Diff
997 lines
51 KiB
Diff
diff --git a/src/vs/base/common/network.ts b/src/vs/base/common/network.ts
|
|
index a68e020f9f..b4ee8a5886 100644
|
|
--- a/src/vs/base/common/network.ts
|
|
+++ b/src/vs/base/common/network.ts
|
|
@@ -88,7 +88,7 @@ class RemoteAuthoritiesImpl {
|
|
if (host && host.indexOf(':') !== -1) {
|
|
host = `[${host}]`;
|
|
}
|
|
- const port = this._ports[authority];
|
|
+ // const port = this._ports[authority];
|
|
const connectionToken = this._connectionTokens[authority];
|
|
let query = `path=${encodeURIComponent(uri.path)}`;
|
|
if (typeof connectionToken === 'string') {
|
|
@@ -96,8 +96,8 @@ class RemoteAuthoritiesImpl {
|
|
}
|
|
return URI.from({
|
|
scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,
|
|
- authority: `${host}:${port}`,
|
|
- path: `/vscode-remote-resource`,
|
|
+ authority: window.location.host,
|
|
+ path: `${window.location.pathname.replace(/\/+$/, '')}/vscode-remote-resource`,
|
|
query
|
|
});
|
|
}
|
|
diff --git a/src/vs/base/common/platform.ts b/src/vs/base/common/platform.ts
|
|
index 5a631e0b39..8a2b1518d6 100644
|
|
--- a/src/vs/base/common/platform.ts
|
|
+++ b/src/vs/base/common/platform.ts
|
|
@@ -59,6 +59,17 @@ if (typeof navigator === 'object' && !isElectronRenderer) {
|
|
_isWeb = true;
|
|
_locale = navigator.language;
|
|
_language = _locale;
|
|
+ // NOTE@coder: make languages work.
|
|
+ const el = typeof document !== 'undefined' && document.getElementById('vscode-remote-nls-configuration');
|
|
+ const rawNlsConfig = el && el.getAttribute('data-settings');
|
|
+ if (rawNlsConfig) {
|
|
+ try {
|
|
+ const nlsConfig: NLSConfig = JSON.parse(rawNlsConfig);
|
|
+ _locale = nlsConfig.locale;
|
|
+ _translationsConfigFile = nlsConfig._translationsConfigFile;
|
|
+ _language = nlsConfig.availableLanguages['*'] || LANGUAGE_DEFAULT;
|
|
+ } catch (error) { /* Oh well. */ }
|
|
+ }
|
|
} else if (typeof process === 'object') {
|
|
_isWindows = (process.platform === 'win32');
|
|
_isMacintosh = (process.platform === 'darwin');
|
|
diff --git a/src/vs/base/common/processes.ts b/src/vs/base/common/processes.ts
|
|
index c52f7b3774..5a7e7f579e 100644
|
|
--- a/src/vs/base/common/processes.ts
|
|
+++ b/src/vs/base/common/processes.ts
|
|
@@ -110,7 +110,10 @@ export function sanitizeProcessEnvironment(env: IProcessEnvironment, ...preserve
|
|
/^ELECTRON_.+$/,
|
|
/^GOOGLE_API_KEY$/,
|
|
/^VSCODE_.+$/,
|
|
- /^SNAP(|_.*)$/
|
|
+ /^SNAP(|_.*)$/,
|
|
+ // NOTE@coder: add our own environment variables.
|
|
+ /^NBIN_BYPASS$/,
|
|
+ /^LAUNCH_VSCODE$/
|
|
];
|
|
const envKeys = Object.keys(env);
|
|
envKeys
|
|
diff --git a/src/vs/base/node/languagePacks.js b/src/vs/base/node/languagePacks.js
|
|
index 2c64061da7..c0ef8faedd 100644
|
|
--- a/src/vs/base/node/languagePacks.js
|
|
+++ b/src/vs/base/node/languagePacks.js
|
|
@@ -128,7 +128,10 @@ function factory(nodeRequire, path, fs, perf) {
|
|
function getLanguagePackConfigurations(userDataPath) {
|
|
const configFile = path.join(userDataPath, 'languagepacks.json');
|
|
try {
|
|
- return nodeRequire(configFile);
|
|
+ // NOTE@coder: Swapped require with readFile since require is cached and
|
|
+ // we don't restart the server-side portion of code-server when the
|
|
+ // language changes.
|
|
+ return JSON.parse(fs.readFileSync(configFile, "utf8"));
|
|
} catch (err) {
|
|
// Do nothing. If we can't read the file we have no
|
|
// language pack config.
|
|
diff --git a/src/vs/code/browser/workbench/workbench.ts b/src/vs/code/browser/workbench/workbench.ts
|
|
index a599f5a7eb..ec7ccd43f8 100644
|
|
--- a/src/vs/code/browser/workbench/workbench.ts
|
|
+++ b/src/vs/code/browser/workbench/workbench.ts
|
|
@@ -298,35 +298,6 @@ class WorkspaceProvider implements IWorkspaceProvider {
|
|
let workspace: IWorkspace;
|
|
let payload = Object.create(null);
|
|
|
|
- const query = new URL(document.location.href).searchParams;
|
|
- query.forEach((value, key) => {
|
|
- switch (key) {
|
|
-
|
|
- // Folder
|
|
- case WorkspaceProvider.QUERY_PARAM_FOLDER:
|
|
- workspace = { folderUri: URI.parse(value) };
|
|
- foundWorkspace = true;
|
|
- break;
|
|
-
|
|
- // Workspace
|
|
- case WorkspaceProvider.QUERY_PARAM_WORKSPACE:
|
|
- workspace = { workspaceUri: URI.parse(value) };
|
|
- foundWorkspace = true;
|
|
- break;
|
|
-
|
|
- // Empty
|
|
- case WorkspaceProvider.QUERY_PARAM_EMPTY_WINDOW:
|
|
- workspace = undefined;
|
|
- foundWorkspace = true;
|
|
- break;
|
|
-
|
|
- // Payload
|
|
- case WorkspaceProvider.QUERY_PARAM_PAYLOAD:
|
|
- payload = JSON.parse(value);
|
|
- break;
|
|
- }
|
|
- });
|
|
-
|
|
// If no workspace is provided through the URL, check for config attribute from server
|
|
if (!foundWorkspace) {
|
|
if (config.folderUri) {
|
|
diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts
|
|
index abd1e33b18..bf75952ce1 100644
|
|
--- a/src/vs/platform/environment/common/environment.ts
|
|
+++ b/src/vs/platform/environment/common/environment.ts
|
|
@@ -37,6 +37,8 @@ export interface ParsedArgs {
|
|
logExtensionHostCommunication?: boolean;
|
|
'extensions-dir'?: string;
|
|
'builtin-extensions-dir'?: string;
|
|
+ 'extra-extensions-dir'?: string[];
|
|
+ 'extra-builtin-extensions-dir'?: string[];
|
|
extensionDevelopmentPath?: string[]; // // undefined or array of 1 or more local paths or URIs
|
|
extensionTestsPath?: string; // either a local path or a URI
|
|
'extension-development-confirm-save'?: boolean;
|
|
@@ -147,6 +149,8 @@ export interface IEnvironmentService extends IUserHomeProvider {
|
|
disableExtensions: boolean | string[];
|
|
builtinExtensionsPath: string;
|
|
extensionsPath?: string;
|
|
+ extraExtensionPaths: string[];
|
|
+ extraBuiltinExtensionPaths: string[];
|
|
extensionDevelopmentLocationURI?: URI[];
|
|
extensionTestsLocationURI?: URI;
|
|
logExtensionHostCommunication?: boolean;
|
|
diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts
|
|
index e68e0647c3..49a5aae2fa 100644
|
|
--- a/src/vs/platform/environment/node/argv.ts
|
|
+++ b/src/vs/platform/environment/node/argv.ts
|
|
@@ -55,6 +55,8 @@ export const OPTIONS: OptionDescriptions<Required<ParsedArgs>> = {
|
|
|
|
'extensions-dir': { type: 'string', deprecates: 'extensionHomePath', cat: 'e', args: 'dir', description: localize('extensionHomePath', "Set the root path for extensions.") },
|
|
'builtin-extensions-dir': { type: 'string' },
|
|
+ 'extra-builtin-extensions-dir': { type: 'string[]', cat: 'o', description: 'Path to an extra builtin extension directory.' },
|
|
+ 'extra-extensions-dir': { type: 'string[]', cat: 'o', description: 'Path to an extra user extension directory.' },
|
|
'list-extensions': { type: 'boolean', cat: 'e', description: localize('listExtensions', "List the installed extensions.") },
|
|
'show-versions': { type: 'boolean', cat: 'e', description: localize('showVersions', "Show versions of installed extensions, when using --list-extension.") },
|
|
'category': { type: 'string', cat: 'e', description: localize('category', "Filters installed extensions by provided category, when using --list-extension.") },
|
|
@@ -310,4 +312,3 @@ export function buildHelpMessage(productName: string, executableName: string, ve
|
|
export function buildVersionMessage(version: string | undefined, commit: string | undefined): string {
|
|
return `${version || localize('unknownVersion', "Unknown version")}\n${commit || localize('unknownCommit', "Unknown commit")}\n${process.arch}`;
|
|
}
|
|
-
|
|
diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts
|
|
index 0428e1e888..9b3cddcb3a 100644
|
|
--- a/src/vs/platform/environment/node/environmentService.ts
|
|
+++ b/src/vs/platform/environment/node/environmentService.ts
|
|
@@ -197,6 +197,13 @@ export class EnvironmentService implements IEnvironmentService {
|
|
return path.join(this.userHome, product.dataFolderName, 'extensions');
|
|
}
|
|
|
|
+ @memoize get extraExtensionPaths(): string[] {
|
|
+ return (this._args['extra-extensions-dir'] || []).map((p) => <string>parsePathArg(p, process));
|
|
+ }
|
|
+ @memoize get extraBuiltinExtensionPaths(): string[] {
|
|
+ return (this._args['extra-builtin-extensions-dir'] || []).map((p) => <string>parsePathArg(p, process));
|
|
+ }
|
|
+
|
|
@memoize
|
|
get extensionDevelopmentLocationURI(): URI[] | undefined {
|
|
const s = this._args.extensionDevelopmentPath;
|
|
diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts
|
|
index 5b05650591..dc5140410e 100644
|
|
--- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts
|
|
+++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts
|
|
@@ -743,11 +743,15 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
|
|
|
private scanSystemExtensions(): Promise<ILocalExtension[]> {
|
|
this.logService.trace('Started scanning system extensions');
|
|
- const systemExtensionsPromise = this.scanExtensions(this.systemExtensionsPath, ExtensionType.System)
|
|
- .then(result => {
|
|
- this.logService.trace('Scanned system extensions:', result.length);
|
|
- return result;
|
|
- });
|
|
+ const systemExtensionsPromise = Promise.all([
|
|
+ this.scanExtensions(this.systemExtensionsPath, ExtensionType.System),
|
|
+ ...this.environmentService.extraBuiltinExtensionPaths
|
|
+ .map((path) => this.scanExtensions(path, ExtensionType.System))
|
|
+ ]).then((results) => {
|
|
+ const result = results.reduce((flat, current) => flat.concat(current), []);
|
|
+ this.logService.trace('Scanned system extensions:', result.length);
|
|
+ return result;
|
|
+ });
|
|
if (this.environmentService.isBuilt) {
|
|
return systemExtensionsPromise;
|
|
}
|
|
@@ -769,9 +773,17 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
|
.then(([systemExtensions, devSystemExtensions]) => [...systemExtensions, ...devSystemExtensions]);
|
|
}
|
|
|
|
+ private scanAllUserExtensions(folderName: string, type: ExtensionType): Promise<ILocalExtension[]> {
|
|
+ return Promise.all([
|
|
+ this.scanExtensions(folderName, type),
|
|
+ ...this.environmentService.extraExtensionPaths.map((p) => this.scanExtensions(p, ExtensionType.User))
|
|
+ ]).then((results) => results.reduce((flat, current) => flat.concat(current), []));
|
|
+ }
|
|
+
|
|
+
|
|
private scanUserExtensions(excludeOutdated: boolean): Promise<ILocalExtension[]> {
|
|
this.logService.trace('Started scanning user extensions');
|
|
- return Promise.all([this.getUninstalledExtensions(), this.scanExtensions(this.extensionsPath, ExtensionType.User)])
|
|
+ return Promise.all([this.getUninstalledExtensions(), this.scanAllUserExtensions(this.extensionsPath, ExtensionType.User)])
|
|
.then(([uninstalled, extensions]) => {
|
|
extensions = extensions.filter(e => !uninstalled[new ExtensionIdentifierWithVersion(e.identifier, e.manifest.version).key()]);
|
|
if (excludeOutdated) {
|
|
@@ -786,6 +798,12 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
|
private scanExtensions(root: string, type: ExtensionType): Promise<ILocalExtension[]> {
|
|
const limiter = new Limiter<any>(10);
|
|
return pfs.readdir(root)
|
|
+ .catch((error) => {
|
|
+ if (error.code !== 'ENOENT') {
|
|
+ throw error;
|
|
+ }
|
|
+ return <string[]>[];
|
|
+ })
|
|
.then(extensionsFolders => Promise.all<ILocalExtension>(extensionsFolders.map(extensionFolder => limiter.queue(() => this.scanExtension(extensionFolder, root, type)))))
|
|
.then(extensions => extensions.filter(e => e && e.identifier));
|
|
}
|
|
@@ -824,7 +842,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
|
|
|
private async removeUninstalledExtensions(): Promise<void> {
|
|
const uninstalled = await this.getUninstalledExtensions();
|
|
- const extensions = await this.scanExtensions(this.extensionsPath, ExtensionType.User); // All user extensions
|
|
+ const extensions = await this.scanAllUserExtensions(this.extensionsPath, ExtensionType.User); // All user extensions
|
|
const installed: Set<string> = new Set<string>();
|
|
for (const e of extensions) {
|
|
if (!uninstalled[new ExtensionIdentifierWithVersion(e.identifier, e.manifest.version).key()]) {
|
|
@@ -843,7 +861,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
|
}
|
|
|
|
private removeOutdatedExtensions(): Promise<void> {
|
|
- return this.scanExtensions(this.extensionsPath, ExtensionType.User) // All user extensions
|
|
+ return this.scanAllUserExtensions(this.extensionsPath, ExtensionType.User) // All user extensions
|
|
.then(extensions => {
|
|
const toRemove: ILocalExtension[] = [];
|
|
|
|
diff --git a/src/vs/platform/product/common/product.ts b/src/vs/platform/product/common/product.ts
|
|
index 804d113856..4b651e5c77 100644
|
|
--- a/src/vs/platform/product/common/product.ts
|
|
+++ b/src/vs/platform/product/common/product.ts
|
|
@@ -22,11 +22,19 @@ if (isWeb) {
|
|
if (Object.keys(product).length === 0) {
|
|
assign(product, {
|
|
version: '1.41.0-dev',
|
|
+ codeServerVersion: 'dev',
|
|
nameLong: 'Visual Studio Code Web Dev',
|
|
nameShort: 'VSCode Web Dev',
|
|
urlProtocol: 'code-oss'
|
|
});
|
|
}
|
|
+
|
|
+ // NOTE@coder: enable injecting settings from the server.
|
|
+ const el = document.getElementById('vscode-remote-product-configuration');
|
|
+ const rawProductConfiguration = el && el.getAttribute('data-settings');
|
|
+ if (rawProductConfiguration) {
|
|
+ assign(product, JSON.parse(rawProductConfiguration));
|
|
+ }
|
|
}
|
|
|
|
// Node: AMD loader
|
|
@@ -36,7 +44,7 @@ else if (typeof require !== 'undefined' && typeof require.__$__nodeRequire === '
|
|
const rootPath = path.dirname(getPathFromAmdModule(require, ''));
|
|
|
|
product = assign({}, require.__$__nodeRequire(path.join(rootPath, 'product.json')) as IProductConfiguration);
|
|
- const pkg = require.__$__nodeRequire(path.join(rootPath, 'package.json')) as { version: string; };
|
|
+ const pkg = require.__$__nodeRequire(path.join(rootPath, 'package.json')) as { version: string; codeServerVersion: string; };
|
|
|
|
// Running out of sources
|
|
if (env['VSCODE_DEV']) {
|
|
@@ -48,7 +56,8 @@ else if (typeof require !== 'undefined' && typeof require.__$__nodeRequire === '
|
|
}
|
|
|
|
assign(product, {
|
|
- version: pkg.version
|
|
+ version: pkg.version,
|
|
+ codeServerVersion: pkg.codeServerVersion,
|
|
});
|
|
}
|
|
|
|
diff --git a/src/vs/platform/product/common/productService.ts b/src/vs/platform/product/common/productService.ts
|
|
index 120fd66644..52547bdb0e 100644
|
|
--- a/src/vs/platform/product/common/productService.ts
|
|
+++ b/src/vs/platform/product/common/productService.ts
|
|
@@ -16,6 +16,7 @@ export interface IProductService extends Readonly<IProductConfiguration> {
|
|
|
|
export interface IProductConfiguration {
|
|
readonly version: string;
|
|
+ readonly codeServerVersion: string;
|
|
readonly date?: string;
|
|
readonly quality?: string;
|
|
readonly commit?: string;
|
|
diff --git a/src/vs/platform/remote/browser/browserSocketFactory.ts b/src/vs/platform/remote/browser/browserSocketFactory.ts
|
|
index d0f6e6b18a..1966fd297d 100644
|
|
--- a/src/vs/platform/remote/browser/browserSocketFactory.ts
|
|
+++ b/src/vs/platform/remote/browser/browserSocketFactory.ts
|
|
@@ -205,7 +205,8 @@ export class BrowserSocketFactory implements ISocketFactory {
|
|
}
|
|
|
|
connect(host: string, port: number, query: string, callback: IConnectCallback): void {
|
|
- const socket = this._webSocketFactory.create(`ws://${host}:${port}/?${query}&skipWebSocketFrames=false`);
|
|
+ // NOTE@coder: Modified to work against the current path.
|
|
+ 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();
|
|
@@ -213,6 +214,3 @@ export class BrowserSocketFactory implements ISocketFactory {
|
|
});
|
|
}
|
|
}
|
|
-
|
|
-
|
|
-
|
|
diff --git a/src/vs/platform/request/common/request.ts b/src/vs/platform/request/common/request.ts
|
|
index 81ec255e65..c94829fc6a 100644
|
|
--- a/src/vs/platform/request/common/request.ts
|
|
+++ b/src/vs/platform/request/common/request.ts
|
|
@@ -16,7 +16,7 @@ export const IRequestService = createDecorator<IRequestService>('requestService'
|
|
export interface IRequestService {
|
|
_serviceBrand: undefined;
|
|
|
|
- request(options: IRequestOptions, token: CancellationToken): Promise<IRequestContext>;
|
|
+ request(options: IRequestOptions, token: CancellationToken, gzip?: boolean): Promise<IRequestContext>;
|
|
|
|
resolveProxy(url: string): Promise<string | undefined>;
|
|
}
|
|
diff --git a/src/vs/platform/request/node/requestService.ts b/src/vs/platform/request/node/requestService.ts
|
|
index ad44dcbc33..7a7b5261ff 100644
|
|
--- a/src/vs/platform/request/node/requestService.ts
|
|
+++ b/src/vs/platform/request/node/requestService.ts
|
|
@@ -57,7 +57,7 @@ export class RequestService extends Disposable implements IRequestService {
|
|
this.authorization = config.http && config.http.proxyAuthorization;
|
|
}
|
|
|
|
- async request(options: NodeRequestOptions, token: CancellationToken): Promise<IRequestContext> {
|
|
+ async request(options: NodeRequestOptions, token: CancellationToken, gzip?: boolean): Promise<IRequestContext> {
|
|
this.logService.trace('RequestService#request', options.url);
|
|
|
|
const { proxyUrl, strictSSL } = this;
|
|
@@ -70,7 +70,7 @@ export class RequestService extends Disposable implements IRequestService {
|
|
options.headers = assign(options.headers || {}, { 'Proxy-Authorization': this.authorization });
|
|
}
|
|
|
|
- return this._request(options, token);
|
|
+ return this._request(options, token, gzip);
|
|
}
|
|
|
|
private async getNodeRequest(options: IRequestOptions): Promise<IRawRequestFunction> {
|
|
@@ -79,7 +79,7 @@ export class RequestService extends Disposable implements IRequestService {
|
|
return module.request;
|
|
}
|
|
|
|
- private _request(options: NodeRequestOptions, token: CancellationToken): Promise<IRequestContext> {
|
|
+ private _request(options: NodeRequestOptions, token: CancellationToken, gzip?: boolean): Promise<IRequestContext> {
|
|
|
|
return new Promise<IRequestContext>(async (c, e) => {
|
|
let req: http.ClientRequest;
|
|
@@ -114,7 +114,7 @@ export class RequestService extends Disposable implements IRequestService {
|
|
} else {
|
|
let stream: streams.ReadableStream<Uint8Array> = res;
|
|
|
|
- if (res.headers['content-encoding'] === 'gzip') {
|
|
+ if (gzip || res.headers['content-encoding'] === 'gzip') {
|
|
stream = res.pipe(createGunzip());
|
|
}
|
|
|
|
diff --git a/src/vs/platform/update/electron-main/abstractUpdateService.ts b/src/vs/platform/update/electron-main/abstractUpdateService.ts
|
|
index d8bf464fed..748715da3b 100644
|
|
--- a/src/vs/platform/update/electron-main/abstractUpdateService.ts
|
|
+++ b/src/vs/platform/update/electron-main/abstractUpdateService.ts
|
|
@@ -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 { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
|
|
import product from 'vs/platform/product/common/product';
|
|
import { IUpdateService, State, StateType, AvailableForDownload, UpdateType } from 'vs/platform/update/common/update';
|
|
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
|
@@ -44,7 +43,7 @@ export abstract class AbstractUpdateService implements IUpdateService {
|
|
}
|
|
|
|
constructor(
|
|
- @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
|
|
+ _: any, // NOTE@coder: This depends on Electron so we skip it.
|
|
@IConfigurationService protected configurationService: IConfigurationService,
|
|
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
|
@IRequestService protected requestService: IRequestService,
|
|
@@ -156,15 +155,8 @@ export abstract class AbstractUpdateService implements IUpdateService {
|
|
|
|
this.logService.trace('update#quitAndInstall(): before lifecycle quit()');
|
|
|
|
- this.lifecycleMainService.quit(true /* from update */).then(vetod => {
|
|
- this.logService.trace(`update#quitAndInstall(): after lifecycle quit() with veto: ${vetod}`);
|
|
- if (vetod) {
|
|
- return;
|
|
- }
|
|
-
|
|
this.logService.trace('update#quitAndInstall(): running raw#quitAndInstall()');
|
|
this.doQuitAndInstall();
|
|
- });
|
|
|
|
return Promise.resolve(undefined);
|
|
}
|
|
diff --git a/src/vs/workbench/api/browser/extensionHost.contribution.ts b/src/vs/workbench/api/browser/extensionHost.contribution.ts
|
|
index e69aa80159..2960d00456 100644
|
|
--- a/src/vs/workbench/api/browser/extensionHost.contribution.ts
|
|
+++ b/src/vs/workbench/api/browser/extensionHost.contribution.ts
|
|
@@ -62,6 +62,7 @@ import './mainThreadTunnelService';
|
|
import './mainThreadAuthentication';
|
|
import './mainThreadTimeline';
|
|
import 'vs/workbench/api/common/apiCommands';
|
|
+import 'vs/server/src/browser/mainThreadNodeProxy';
|
|
|
|
export class ExtensionPoints implements IWorkbenchContribution {
|
|
|
|
diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts
|
|
index 91045fcda6..d93d3286d8 100644
|
|
--- a/src/vs/workbench/api/common/extHost.api.impl.ts
|
|
+++ b/src/vs/workbench/api/common/extHost.api.impl.ts
|
|
@@ -72,6 +72,7 @@ import { IExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelServ
|
|
import { IExtHostApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
|
|
import { ExtHostAuthentication } from 'vs/workbench/api/common/extHostAuthentication';
|
|
import { ExtHostTimeline } from 'vs/workbench/api/common/extHostTimeline';
|
|
+import { IExtHostNodeProxy } from 'vs/server/src/browser/extHostNodeProxy';
|
|
|
|
export interface IExtensionApiFactory {
|
|
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
|
|
@@ -93,6 +94,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
|
const extHostLogService = accessor.get(ILogService);
|
|
const extHostTunnelService = accessor.get(IExtHostTunnelService);
|
|
const extHostApiDeprecation = accessor.get(IExtHostApiDeprecationService);
|
|
+ const extHostNodeProxy = accessor.get(IExtHostNodeProxy);
|
|
|
|
// register addressable instances
|
|
rpcProtocol.set(ExtHostContext.ExtHostLogService, <ExtHostLogServiceShape><any>extHostLogService);
|
|
@@ -101,6 +103,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
|
rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService);
|
|
rpcProtocol.set(ExtHostContext.ExtHostStorage, extHostStorage);
|
|
rpcProtocol.set(ExtHostContext.ExtHostTunnelService, extHostTunnelService);
|
|
+ rpcProtocol.set(ExtHostContext.ExtHostNodeProxy, extHostNodeProxy);
|
|
|
|
// automatically create and register addressable instances
|
|
const extHostDecorations = rpcProtocol.set(ExtHostContext.ExtHostDecorations, accessor.get(IExtHostDecorations));
|
|
diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts
|
|
index 55130ff918..032534b23e 100644
|
|
--- a/src/vs/workbench/api/common/extHost.protocol.ts
|
|
+++ b/src/vs/workbench/api/common/extHost.protocol.ts
|
|
@@ -667,6 +667,16 @@ export interface MainThreadLabelServiceShape extends IDisposable {
|
|
$unregisterResourceLabelFormatter(handle: number): void;
|
|
}
|
|
|
|
+export interface MainThreadNodeProxyShape extends IDisposable {
|
|
+ $send(message: string): void;
|
|
+}
|
|
+export interface ExtHostNodeProxyShape {
|
|
+ $onMessage(message: string): void;
|
|
+ $onClose(): void;
|
|
+ $onDown(): void;
|
|
+ $onUp(): void;
|
|
+}
|
|
+
|
|
export interface MainThreadSearchShape extends IDisposable {
|
|
$registerFileSearchProvider(handle: number, scheme: string): void;
|
|
$registerTextSearchProvider(handle: number, scheme: string): void;
|
|
@@ -1498,7 +1508,8 @@ export const MainContext = {
|
|
MainThreadLabelService: createMainId<MainThreadLabelServiceShape>('MainThreadLabelService'),
|
|
MainThreadTheming: createMainId<MainThreadThemingShape>('MainThreadTheming'),
|
|
MainThreadTunnelService: createMainId<MainThreadTunnelServiceShape>('MainThreadTunnelService'),
|
|
- MainThreadTimeline: createMainId<MainThreadTimelineShape>('MainThreadTimeline')
|
|
+ MainThreadTimeline: createMainId<MainThreadTimelineShape>('MainThreadTimeline'),
|
|
+ MainThreadNodeProxy: createMainId<MainThreadNodeProxyShape>('MainThreadNodeProxy'),
|
|
};
|
|
|
|
export const ExtHostContext = {
|
|
@@ -1536,5 +1547,6 @@ export const ExtHostContext = {
|
|
ExtHostTheming: createMainId<ExtHostThemingShape>('ExtHostTheming'),
|
|
ExtHostTunnelService: createMainId<ExtHostTunnelServiceShape>('ExtHostTunnelService'),
|
|
ExtHostAuthentication: createMainId<ExtHostAuthenticationShape>('ExtHostAuthentication'),
|
|
- ExtHostTimeline: createMainId<ExtHostTimelineShape>('ExtHostTimeline')
|
|
+ ExtHostTimeline: createMainId<ExtHostTimelineShape>('ExtHostTimeline'),
|
|
+ ExtHostNodeProxy: createMainId<ExtHostNodeProxyShape>('ExtHostNodeProxy')
|
|
};
|
|
diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts
|
|
index 978bf32fcd..a63954cce0 100644
|
|
--- a/src/vs/workbench/api/common/extHostExtensionService.ts
|
|
+++ b/src/vs/workbench/api/common/extHostExtensionService.ts
|
|
@@ -5,7 +5,7 @@
|
|
|
|
import * as nls from 'vs/nls';
|
|
import * as path from 'vs/base/common/path';
|
|
-import { originalFSPath, joinPath } from 'vs/base/common/resources';
|
|
+import { originalFSPath } from 'vs/base/common/resources';
|
|
import { Barrier } from 'vs/base/common/async';
|
|
import { dispose, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
|
import { TernarySearchTree } from 'vs/base/common/map';
|
|
@@ -33,6 +33,7 @@ import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePa
|
|
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
|
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
|
import { IExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService';
|
|
+import { IExtHostNodeProxy } from 'vs/server/src/browser/extHostNodeProxy';
|
|
|
|
interface ITestRunner {
|
|
/** Old test runner API, as exported from `vscode/lib/testrunner` */
|
|
@@ -78,6 +79,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
|
|
protected readonly _extHostConfiguration: ExtHostConfiguration;
|
|
protected readonly _logService: ILogService;
|
|
protected readonly _extHostTunnelService: IExtHostTunnelService;
|
|
+ protected readonly _nodeProxy: IExtHostNodeProxy;
|
|
|
|
protected readonly _mainThreadWorkspaceProxy: MainThreadWorkspaceShape;
|
|
protected readonly _mainThreadTelemetryProxy: MainThreadTelemetryShape;
|
|
@@ -107,7 +109,8 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
|
|
@ILogService logService: ILogService,
|
|
@IExtHostInitDataService initData: IExtHostInitDataService,
|
|
@IExtensionStoragePaths storagePath: IExtensionStoragePaths,
|
|
- @IExtHostTunnelService extHostTunnelService: IExtHostTunnelService
|
|
+ @IExtHostTunnelService extHostTunnelService: IExtHostTunnelService,
|
|
+ @IExtHostNodeProxy nodeProxy: IExtHostNodeProxy,
|
|
) {
|
|
this._hostUtils = hostUtils;
|
|
this._extHostContext = extHostContext;
|
|
@@ -116,6 +119,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
|
|
this._extHostWorkspace = extHostWorkspace;
|
|
this._extHostConfiguration = extHostConfiguration;
|
|
this._logService = logService;
|
|
+ this._nodeProxy = nodeProxy;
|
|
this._extHostTunnelService = extHostTunnelService;
|
|
this._disposables = new DisposableStore();
|
|
|
|
@@ -341,14 +345,14 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
|
|
|
|
const activationTimesBuilder = new ExtensionActivationTimesBuilder(reason.startup);
|
|
return Promise.all([
|
|
- this._loadCommonJSModule<IExtensionModule>(joinPath(extensionDescription.extensionLocation, extensionDescription.main), activationTimesBuilder),
|
|
+ this._loadCommonJSModule<IExtensionModule>(extensionDescription, activationTimesBuilder),
|
|
this._loadExtensionContext(extensionDescription)
|
|
]).then(values => {
|
|
return AbstractExtHostExtensionService._callActivate(this._logService, extensionDescription.identifier, values[0], values[1], activationTimesBuilder);
|
|
});
|
|
}
|
|
|
|
- protected abstract _loadCommonJSModule<T>(module: URI, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T>;
|
|
+ protected abstract _loadCommonJSModule<T>(module: URI | IExtensionDescription, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T>;
|
|
|
|
private _loadExtensionContext(extensionDescription: IExtensionDescription): Promise<vscode.ExtensionContext> {
|
|
|
|
diff --git a/src/vs/workbench/api/node/extHost.services.ts b/src/vs/workbench/api/node/extHost.services.ts
|
|
index 72ad75d63e..8c4edee5e3 100644
|
|
--- a/src/vs/workbench/api/node/extHost.services.ts
|
|
+++ b/src/vs/workbench/api/node/extHost.services.ts
|
|
@@ -29,6 +29,8 @@ import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
|
|
import { IExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService';
|
|
import { ExtHostTunnelService } from 'vs/workbench/api/node/extHostTunnelService';
|
|
import { IExtHostApiDeprecationService, ExtHostApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
|
|
+import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
|
|
+import { IExtHostNodeProxy } from 'vs/server/src/browser/extHostNodeProxy';
|
|
|
|
// register singleton services
|
|
registerSingleton(ILogService, ExtHostLogService);
|
|
@@ -47,3 +49,19 @@ registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths);
|
|
registerSingleton(IExtHostExtensionService, ExtHostExtensionService);
|
|
registerSingleton(IExtHostStorage, ExtHostStorage);
|
|
registerSingleton(IExtHostTunnelService, ExtHostTunnelService);
|
|
+
|
|
+function NotImplementedProxy<T>(name: ServiceIdentifier<T>): { new(): T } {
|
|
+ return <any>class {
|
|
+ constructor() {
|
|
+ return new Proxy({}, {
|
|
+ get(target: any, prop: string | number) {
|
|
+ if (target[prop]) {
|
|
+ return target[prop];
|
|
+ }
|
|
+ throw new Error(`Not Implemented: ${name}->${String(prop)}`);
|
|
+ }
|
|
+ });
|
|
+ }
|
|
+ };
|
|
+}
|
|
+registerSingleton(IExtHostNodeProxy, class extends NotImplementedProxy(IExtHostNodeProxy) {});
|
|
diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts
|
|
index a1c3e50ffd..910627aaf9 100644
|
|
--- a/src/vs/workbench/api/node/extHostExtensionService.ts
|
|
+++ b/src/vs/workbench/api/node/extHostExtensionService.ts
|
|
@@ -13,6 +13,8 @@ import { ExtHostDownloadService } from 'vs/workbench/api/node/extHostDownloadSer
|
|
import { CLIServer } from 'vs/workbench/api/node/extHostCLIServer';
|
|
import { URI } from 'vs/base/common/uri';
|
|
import { Schemas } from 'vs/base/common/network';
|
|
+import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
|
+import { joinPath } from 'vs/base/common/resources';
|
|
|
|
class NodeModuleRequireInterceptor extends RequireInterceptor {
|
|
|
|
@@ -76,7 +78,10 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService {
|
|
};
|
|
}
|
|
|
|
- protected _loadCommonJSModule<T>(module: URI, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T> {
|
|
+ protected _loadCommonJSModule<T>(module: URI | IExtensionDescription, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T> {
|
|
+ if (!URI.isUri(module)) {
|
|
+ module = joinPath(module.extensionLocation, module.main!);
|
|
+ }
|
|
if (module.scheme !== Schemas.file) {
|
|
throw new Error(`Cannot load URI: '${module}', must be of file-scheme`);
|
|
}
|
|
diff --git a/src/vs/workbench/api/node/extHostStoragePaths.ts b/src/vs/workbench/api/node/extHostStoragePaths.ts
|
|
index afdd6bf398..ac91318ce3 100644
|
|
--- a/src/vs/workbench/api/node/extHostStoragePaths.ts
|
|
+++ b/src/vs/workbench/api/node/extHostStoragePaths.ts
|
|
@@ -5,13 +5,14 @@
|
|
|
|
import * as path from 'vs/base/common/path';
|
|
import { URI } from 'vs/base/common/uri';
|
|
-import * as pfs from 'vs/base/node/pfs';
|
|
-import { IEnvironment, IStaticWorkspaceData } from 'vs/workbench/api/common/extHost.protocol';
|
|
+import { IEnvironment, IStaticWorkspaceData, MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
|
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
|
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
|
|
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
|
import { withNullAsUndefined } from 'vs/base/common/types';
|
|
import { ILogService } from 'vs/platform/log/common/log';
|
|
+import { IExtHostRpcService } from '../common/extHostRpcService';
|
|
+import { VSBuffer } from 'vs/base/common/buffer';
|
|
|
|
export class ExtensionStoragePaths implements IExtensionStoragePaths {
|
|
|
|
@@ -26,6 +27,7 @@ export class ExtensionStoragePaths implements IExtensionStoragePaths {
|
|
constructor(
|
|
@IExtHostInitDataService initData: IExtHostInitDataService,
|
|
@ILogService private readonly _logService: ILogService,
|
|
+ @IExtHostRpcService private readonly _extHostRpc: IExtHostRpcService,
|
|
) {
|
|
this._workspace = withNullAsUndefined(initData.workspace);
|
|
this._environment = initData.environment;
|
|
@@ -54,21 +56,25 @@ export class ExtensionStoragePaths implements IExtensionStoragePaths {
|
|
const storageName = this._workspace.id;
|
|
const storagePath = path.join(this._environment.appSettingsHome.fsPath, 'workspaceStorage', storageName);
|
|
|
|
- const exists = await pfs.dirExists(storagePath);
|
|
+ // NOTE@coder: Use the file system proxy so this will work in the browser.
|
|
+ // writeFile performs a mkdirp so we don't need to bother ourselves.
|
|
+ const fileSystem = this._extHostRpc.getProxy(MainContext.MainThreadFileSystem);
|
|
+ const exists = fileSystem.$stat(URI.file(storagePath))
|
|
|
|
if (exists) {
|
|
return storagePath;
|
|
}
|
|
|
|
try {
|
|
- await pfs.mkdirp(storagePath);
|
|
- await pfs.writeFile(
|
|
- path.join(storagePath, 'meta.json'),
|
|
- JSON.stringify({
|
|
- id: this._workspace.id,
|
|
- configuration: this._workspace.configuration && URI.revive(this._workspace.configuration).toString(),
|
|
- name: this._workspace.name
|
|
- }, undefined, 2)
|
|
+ await fileSystem.$writeFile(
|
|
+ URI.file(path.join(storagePath, 'meta.json')),
|
|
+ VSBuffer.fromString(
|
|
+ JSON.stringify({
|
|
+ id: this._workspace.id,
|
|
+ configuration: this._workspace.configuration && URI.revive(this._workspace.configuration).toString(),
|
|
+ name: this._workspace.name
|
|
+ }, undefined, 2)
|
|
+ )
|
|
);
|
|
return storagePath;
|
|
|
|
diff --git a/src/vs/workbench/api/worker/extHostExtensionService.ts b/src/vs/workbench/api/worker/extHostExtensionService.ts
|
|
index 4781f22676..25143a97c0 100644
|
|
--- a/src/vs/workbench/api/worker/extHostExtensionService.ts
|
|
+++ b/src/vs/workbench/api/worker/extHostExtensionService.ts
|
|
@@ -9,6 +9,9 @@ import { AbstractExtHostExtensionService } from 'vs/workbench/api/common/extHost
|
|
import { endsWith } from 'vs/base/common/strings';
|
|
import { URI } from 'vs/base/common/uri';
|
|
import { RequireInterceptor } from 'vs/workbench/api/common/extHostRequireInterceptor';
|
|
+import { joinPath } from 'vs/base/common/resources';
|
|
+import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
|
+import { loadCommonJSModule } from 'vs/server/src/browser/worker';
|
|
|
|
class WorkerRequireInterceptor extends RequireInterceptor {
|
|
|
|
@@ -41,7 +44,14 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService {
|
|
await this._fakeModules.install();
|
|
}
|
|
|
|
- protected async _loadCommonJSModule<T>(module: URI, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T> {
|
|
+ protected async _loadCommonJSModule<T>(module: URI | IExtensionDescription, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T> {
|
|
+ if (!URI.isUri(module) && module.extensionKind !== 'web') {
|
|
+ return loadCommonJSModule(module, activationTimesBuilder, this._nodeProxy, this._logService, this._fakeModules!.getModule('vscode', module.extensionLocation));
|
|
+ }
|
|
+
|
|
+ if (!URI.isUri(module)) {
|
|
+ module = joinPath(module.extensionLocation, module.main!);
|
|
+ }
|
|
|
|
module = module.with({ path: ensureSuffix(module.path, '.js') });
|
|
const response = await fetch(module.toString(true));
|
|
@@ -57,7 +67,7 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService {
|
|
const _exports = {};
|
|
const _module = { exports: _exports };
|
|
const _require = (request: string) => {
|
|
- const result = this._fakeModules!.getModule(request, module);
|
|
+ const result = this._fakeModules!.getModule(request, <URI>module);
|
|
if (result === undefined) {
|
|
throw new Error(`Cannot load module '${request}'`);
|
|
}
|
|
diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts
|
|
index 94e7052574..7e5563b417 100644
|
|
--- a/src/vs/workbench/browser/web.main.ts
|
|
+++ b/src/vs/workbench/browser/web.main.ts
|
|
@@ -49,6 +49,7 @@ import { IndexedDBLogProvider } from 'vs/workbench/services/log/browser/indexedD
|
|
import { InMemoryLogProvider } from 'vs/workbench/services/log/common/inMemoryLogProvider';
|
|
import { isWorkspaceToOpen, isFolderToOpen } from 'vs/platform/windows/common/windows';
|
|
import { getWorkspaceIdentifier } from 'vs/workbench/services/workspaces/browser/workspaces';
|
|
+import { initialize } from 'vs/server/src/browser/client';
|
|
|
|
class BrowserMain extends Disposable {
|
|
|
|
@@ -85,6 +86,7 @@ class BrowserMain extends Disposable {
|
|
|
|
// Startup
|
|
workbench.startup();
|
|
+ await initialize(services.serviceCollection);
|
|
}
|
|
|
|
private registerListeners(workbench: Workbench, storageService: BrowserStorageService): void {
|
|
diff --git a/src/vs/workbench/common/resources.ts b/src/vs/workbench/common/resources.ts
|
|
index c509716fc4..e416413084 100644
|
|
--- a/src/vs/workbench/common/resources.ts
|
|
+++ b/src/vs/workbench/common/resources.ts
|
|
@@ -15,6 +15,7 @@ import { ParsedExpression, IExpression, parse } from 'vs/base/common/glob';
|
|
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
|
import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
|
|
import { withNullAsUndefined } from 'vs/base/common/types';
|
|
+import { Schemas } from 'vs/base/common/network';
|
|
|
|
export class ResourceContextKey extends Disposable implements IContextKey<URI> {
|
|
|
|
@@ -63,7 +64,8 @@ export class ResourceContextKey extends Disposable implements IContextKey<URI> {
|
|
set(value: URI | null) {
|
|
if (!ResourceContextKey._uriEquals(this._resourceKey.get(), value)) {
|
|
this._resourceKey.set(value);
|
|
- this._schemeKey.set(value ? value.scheme : null);
|
|
+ // NOTE@coder: fixes extensions matching against file schemas.
|
|
+ this._schemeKey.set(value ? (value.scheme === Schemas.vscodeRemote ? Schemas.file : value.scheme) : null);
|
|
this._filenameKey.set(value ? basename(value) : null);
|
|
this._langIdKey.set(value ? this._modeService.getModeIdByFilepathOrFirstLine(value) : null);
|
|
this._extensionKey.set(value ? extname(value) : null);
|
|
diff --git a/src/vs/workbench/contrib/webview/browser/pre/main.js b/src/vs/workbench/contrib/webview/browser/pre/main.js
|
|
index 63c9af47e2..021358fef9 100644
|
|
--- a/src/vs/workbench/contrib/webview/browser/pre/main.js
|
|
+++ b/src/vs/workbench/contrib/webview/browser/pre/main.js
|
|
@@ -329,7 +329,8 @@
|
|
if (data.endpoint) {
|
|
try {
|
|
const endpointUrl = new URL(data.endpoint);
|
|
- csp.setAttribute('content', csp.getAttribute('content').replace(/vscode-resource:(?=(\s|;|$))/g, endpointUrl.origin));
|
|
+ // NOTE@coder: Add back the trailing slash so it'll work for sub-paths.
|
|
+ csp.setAttribute('content', csp.getAttribute('content').replace(/vscode-resource:(?=(\s|;|$))/g, endpointUrl.origin + "/"));
|
|
} catch (e) {
|
|
console.error('Could not rewrite csp');
|
|
}
|
|
diff --git a/src/vs/workbench/services/dialogs/browser/dialogService.ts b/src/vs/workbench/services/dialogs/browser/dialogService.ts
|
|
index f67f9aa064..add754cd5a 100644
|
|
--- a/src/vs/workbench/services/dialogs/browser/dialogService.ts
|
|
+++ b/src/vs/workbench/services/dialogs/browser/dialogService.ts
|
|
@@ -122,11 +122,12 @@ export class DialogService implements IDialogService {
|
|
|
|
async about(): Promise<void> {
|
|
const detail = nls.localize('aboutDetail',
|
|
- "Version: {0}\nCommit: {1}\nDate: {2}\nBrowser: {3}",
|
|
+ "Version: {0}\nCommit: {1}\nDate: {2}\nBrowser: {3}\nCode Server Version: {4}",
|
|
this.productService.version || 'Unknown',
|
|
this.productService.commit || 'Unknown',
|
|
this.productService.date || 'Unknown',
|
|
- navigator.userAgent
|
|
+ navigator.userAgent,
|
|
+ this.productService.codeServerVersion || 'Unknown',
|
|
);
|
|
|
|
const { choice } = await this.show(Severity.Info, this.productService.nameLong, [nls.localize('copy', "Copy"), nls.localize('ok', "OK")], { detail, cancelId: 1 });
|
|
diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts
|
|
index 1bf4cfad2a..924a2fcd87 100644
|
|
--- a/src/vs/workbench/services/environment/browser/environmentService.ts
|
|
+++ b/src/vs/workbench/services/environment/browser/environmentService.ts
|
|
@@ -195,8 +195,8 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
|
|
|
|
@memoize
|
|
get webviewExternalEndpoint(): string {
|
|
- // TODO: get fallback from product.json
|
|
- return (this.options.webviewEndpoint || 'https://{{uuid}}.vscode-webview-test.com/{{commit}}').replace('{{commit}}', product.commit || '0d728c31ebdf03869d2687d9be0b017667c9ff37');
|
|
+ // NOTE@coder: Modified to work against the current URL.
|
|
+ return `${window.location.origin}${window.location.pathname.replace(/\/+$/, '')}/webview/`;
|
|
}
|
|
|
|
@memoize
|
|
@@ -249,6 +249,8 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
|
|
installSourcePath!: string;
|
|
|
|
builtinExtensionsPath!: string;
|
|
+ extraExtensionPaths!: string[];
|
|
+ extraBuiltinExtensionPaths!: string[];
|
|
|
|
globalStorageHome!: string;
|
|
workspaceStorageHome!: string;
|
|
diff --git a/src/vs/workbench/services/extensions/browser/extensionService.ts b/src/vs/workbench/services/extensions/browser/extensionService.ts
|
|
index fe891a042e..21d0d4bf61 100644
|
|
--- a/src/vs/workbench/services/extensions/browser/extensionService.ts
|
|
+++ b/src/vs/workbench/services/extensions/browser/extensionService.ts
|
|
@@ -119,6 +119,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
|
|
|
} else {
|
|
// remote: only enabled and none-web'ish extension
|
|
+ localExtensions.push(...remoteEnv.extensions.filter(extension => this._isEnabled(extension) && canExecuteOnWeb(extension, this._productService, this._configService)));
|
|
remoteEnv.extensions = remoteEnv.extensions.filter(extension => this._isEnabled(extension) && !canExecuteOnWeb(extension, this._productService, this._configService));
|
|
this._checkEnableProposedApi(remoteEnv.extensions);
|
|
|
|
diff --git a/src/vs/workbench/services/extensions/common/extensionsUtil.ts b/src/vs/workbench/services/extensions/common/extensionsUtil.ts
|
|
index 9e8352ac88..2d1cb0a107 100644
|
|
--- a/src/vs/workbench/services/extensions/common/extensionsUtil.ts
|
|
+++ b/src/vs/workbench/services/extensions/common/extensionsUtil.ts
|
|
@@ -32,7 +32,8 @@ export function canExecuteOnWorkspace(manifest: IExtensionManifest, productServi
|
|
|
|
export function canExecuteOnWeb(manifest: IExtensionManifest, productService: IProductService, configurationService: IConfigurationService): boolean {
|
|
const extensionKind = getExtensionKind(manifest, productService, configurationService);
|
|
- return extensionKind.some(kind => kind === 'web');
|
|
+ // NOTE@coder: hardcode vim for now.
|
|
+ return extensionKind.some(kind => kind === 'web') || manifest.name === 'vim';
|
|
}
|
|
|
|
export function getExtensionKind(manifest: IExtensionManifest, productService: IProductService, configurationService: IConfigurationService): ExtensionKind[] {
|
|
diff --git a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts
|
|
index 0f35c54431..32fff09b18 100644
|
|
--- a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts
|
|
+++ b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts
|
|
@@ -53,12 +53,13 @@ const args = minimist(process.argv.slice(2), {
|
|
const Module = require.__$__nodeRequire('module') as any;
|
|
const originalLoad = Module._load;
|
|
|
|
- Module._load = function (request: string) {
|
|
+ Module._load = function (request: string, parent: object, isMain: boolean) {
|
|
if (request === 'natives') {
|
|
throw new Error('Either the extension or a NPM dependency is using the "natives" node module which is unsupported as it can cause a crash of the extension host. Click [here](https://go.microsoft.com/fwlink/?linkid=871887) to find out more');
|
|
}
|
|
|
|
- return originalLoad.apply(this, arguments);
|
|
+ // NOTE@coder: Map node_module.asar requests to regular node_modules.
|
|
+ return originalLoad.apply(this, [request.replace(/node_modules\.asar(\.unpacked)?/, 'node_modules'), parent, isMain]);
|
|
};
|
|
})();
|
|
|
|
@@ -131,8 +132,11 @@ function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
|
|
|
|
// Wait for rich client to reconnect
|
|
protocol.onSocketClose(() => {
|
|
- // The socket has closed, let's give the renderer a certain amount of time to reconnect
|
|
- disconnectRunner1.schedule();
|
|
+ // NOTE@coder: Inform the server so we can manage offline
|
|
+ // connections there instead. Our goal is to persist connections
|
|
+ // forever (to a reasonable point) to account for things like
|
|
+ // hibernating overnight.
|
|
+ process.send!({ type: 'VSCODE_EXTHOST_DISCONNECTED' });
|
|
});
|
|
}
|
|
}
|
|
diff --git a/src/vs/workbench/services/extensions/worker/extHost.services.ts b/src/vs/workbench/services/extensions/worker/extHost.services.ts
|
|
index bbb72e9511..63f1f6ff46 100644
|
|
--- a/src/vs/workbench/services/extensions/worker/extHost.services.ts
|
|
+++ b/src/vs/workbench/services/extensions/worker/extHost.services.ts
|
|
@@ -18,11 +18,12 @@ import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePa
|
|
import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
|
|
import { IExtHostStorage, ExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
|
|
import { ExtHostExtensionService } from 'vs/workbench/api/worker/extHostExtensionService';
|
|
-import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
|
|
import { ILogService } from 'vs/platform/log/common/log';
|
|
import { ExtHostLogService } from 'vs/workbench/api/worker/extHostLogService';
|
|
import { IExtHostTunnelService, ExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService';
|
|
import { IExtHostApiDeprecationService, ExtHostApiDeprecationService, } from 'vs/workbench/api/common/extHostApiDeprecationService';
|
|
+import { ExtHostNodeProxy, IExtHostNodeProxy } from 'vs/server/src/browser/extHostNodeProxy';
|
|
+import { ExtensionStoragePaths } from 'vs/workbench/api/node/extHostStoragePaths';
|
|
|
|
// register singleton services
|
|
registerSingleton(ILogService, ExtHostLogService);
|
|
@@ -37,23 +38,9 @@ registerSingleton(IExtHostStorage, ExtHostStorage);
|
|
registerSingleton(IExtHostExtensionService, ExtHostExtensionService);
|
|
registerSingleton(IExtHostSearch, ExtHostSearch);
|
|
registerSingleton(IExtHostTunnelService, ExtHostTunnelService);
|
|
+registerSingleton(IExtHostNodeProxy, ExtHostNodeProxy);
|
|
|
|
-// register services that only throw errors
|
|
-function NotImplementedProxy<T>(name: ServiceIdentifier<T>): { new(): T } {
|
|
- return <any>class {
|
|
- constructor() {
|
|
- return new Proxy({}, {
|
|
- get(target: any, prop: string | number) {
|
|
- if (target[prop]) {
|
|
- return target[prop];
|
|
- }
|
|
- throw new Error(`Not Implemented: ${name}->${String(prop)}`);
|
|
- }
|
|
- });
|
|
- }
|
|
- };
|
|
-}
|
|
registerSingleton(IExtHostTerminalService, WorkerExtHostTerminalService);
|
|
registerSingleton(IExtHostTask, WorkerExtHostTask);
|
|
registerSingleton(IExtHostDebugService, WorkerExtHostDebugService);
|
|
-registerSingleton(IExtensionStoragePaths, class extends NotImplementedProxy(IExtensionStoragePaths) { whenReady = Promise.resolve(); });
|
|
+registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths);
|
|
diff --git a/src/vs/workbench/services/localizations/electron-browser/localizationsService.ts b/src/vs/workbench/services/localizations/electron-browser/localizationsService.ts
|
|
index 99394090da..4891e0fece 100644
|
|
--- a/src/vs/workbench/services/localizations/electron-browser/localizationsService.ts
|
|
+++ b/src/vs/workbench/services/localizations/electron-browser/localizationsService.ts
|
|
@@ -5,17 +5,17 @@
|
|
|
|
import { createChannelSender } from 'vs/base/parts/ipc/node/ipc';
|
|
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
|
|
-import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
|
|
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
|
+import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
|
|
|
export class LocalizationsService {
|
|
|
|
_serviceBrand: undefined;
|
|
|
|
constructor(
|
|
- @ISharedProcessService sharedProcessService: ISharedProcessService,
|
|
+ @IRemoteAgentService remoteAgentService: IRemoteAgentService,
|
|
) {
|
|
- return createChannelSender<ILocalizationsService>(sharedProcessService.getChannel('localizations'));
|
|
+ return createChannelSender<ILocalizationsService>(remoteAgentService.getConnection()!.getChannel('localizations'));
|
|
}
|
|
}
|
|
|
|
diff --git a/src/vs/workbench/services/update/electron-browser/updateService.ts b/src/vs/workbench/services/update/electron-browser/updateService.ts
|
|
index b8f6558b2c..7aeafe6e0e 100644
|
|
--- a/src/vs/workbench/services/update/electron-browser/updateService.ts
|
|
+++ b/src/vs/workbench/services/update/electron-browser/updateService.ts
|
|
@@ -6,8 +6,8 @@
|
|
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 { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
|
+import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
|
|
|
export class NativeUpdateService implements IUpdateService {
|
|
|
|
@@ -21,8 +21,9 @@ export class NativeUpdateService implements IUpdateService {
|
|
|
|
private channel: IChannel;
|
|
|
|
- constructor(@IMainProcessService mainProcessService: IMainProcessService) {
|
|
- this.channel = mainProcessService.getChannel('update');
|
|
+ // NOTE@coder: patched to work in the browser.
|
|
+ constructor(@IRemoteAgentService remoteAgentService: IRemoteAgentService) {
|
|
+ this.channel = remoteAgentService.getConnection()!.getChannel('update');
|
|
|
|
// always set this._state as the state changes
|
|
this.onStateChange(state => this._state = state);
|
|
diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts
|
|
index 0719b361e0..3a4c5cefe8 100644
|
|
--- a/src/vs/workbench/workbench.web.main.ts
|
|
+++ b/src/vs/workbench/workbench.web.main.ts
|
|
@@ -34,11 +34,14 @@ import 'vs/workbench/services/textfile/browser/browserTextFileService';
|
|
import 'vs/workbench/services/keybinding/browser/keymapService';
|
|
import 'vs/workbench/services/extensions/browser/extensionService';
|
|
import 'vs/workbench/services/extensionManagement/common/extensionManagementServerService';
|
|
-import 'vs/workbench/services/telemetry/browser/telemetryService';
|
|
+// NOTE@coder: We send it all to the server side to be processed there instead.
|
|
+// import 'vs/workbench/services/telemetry/browser/telemetryService';
|
|
import 'vs/workbench/services/configurationResolver/browser/configurationResolverService';
|
|
import 'vs/workbench/services/credentials/browser/credentialsService';
|
|
import 'vs/workbench/services/url/browser/urlService';
|
|
-import 'vs/workbench/services/update/browser/updateService';
|
|
+// NOTE@coder: Use the electron-browser version since it already comes with a
|
|
+// channel which lets us actually perform updates.
|
|
+import 'vs/workbench/services/update/electron-browser/updateService';
|
|
import 'vs/workbench/contrib/tags/browser/workspaceTagsService';
|
|
import 'vs/workbench/services/workspaces/browser/workspacesService';
|
|
import 'vs/workbench/services/workspaces/browser/workspaceEditingService';
|