diff --git a/src/vs/workbench/electron-main/main.ts b/src/vs/workbench/electron-main/main.ts index 05624ff115d..e1f5ca381c5 100644 --- a/src/vs/workbench/electron-main/main.ts +++ b/src/vs/workbench/electron-main/main.ts @@ -123,7 +123,7 @@ function main(ipcServer: Server, userEnv: IEnv): void { lifecycle.manager.ready(); // Load settings - settings.manager.load(); + settings.manager.loadSync(); // Propagate to clients windows.manager.ready(userEnv); diff --git a/src/vs/workbench/electron-main/settings.ts b/src/vs/workbench/electron-main/settings.ts index e1b86a8c7dd..9bfab0a387b 100644 --- a/src/vs/workbench/electron-main/settings.ts +++ b/src/vs/workbench/electron-main/settings.ts @@ -20,8 +20,8 @@ export class SettingsManager extends UserSettings { }); } - public load(): boolean { - const settingsChanged = super.load(); + public loadSync(): boolean { + const settingsChanged = super.loadSync(); // Store into global so that any renderer can access the value with remote.getGlobal() if (settingsChanged) { diff --git a/src/vs/workbench/node/userSettings.ts b/src/vs/workbench/node/userSettings.ts index 309efa511d8..83dd90840a2 100644 --- a/src/vs/workbench/node/userSettings.ts +++ b/src/vs/workbench/node/userSettings.ts @@ -12,7 +12,9 @@ import path = require('path'); import json = require('vs/base/common/json'); import objects = require('vs/base/common/objects'); import {EventProvider} from 'vs/base/common/eventProvider'; +import {TPromise} from 'vs/base/common/winjs.base'; import {EventSource} from 'vs/base/common/eventSource'; +import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService'; export interface ISettings { settings: any; @@ -33,7 +35,7 @@ export class UserSettings { private _onChange: EventSource<(settings: ISettings) => void>; - constructor(appSettingsPath:string, appKeybindingsPath: string) { + constructor(appSettingsPath: string, appKeybindingsPath: string) { this.appSettingsPath = appSettingsPath; this.appKeybindingsPath = appKeybindingsPath; this._onChange = new EventSource<(settings: ISettings) => void>(); @@ -41,16 +43,45 @@ export class UserSettings { this.registerWatchers(); } + public static getValue(contextService: IWorkspaceContextService, key: string, fallback?: any): TPromise { + return new TPromise((c, e) => { + const appSettingsPath = contextService.getConfiguration().env.appSettingsPath; + + fs.readFile(appSettingsPath, (error /* ignore */, fileContents) => { + let root = {}; + let content = fileContents && fileContents.toString(); + if (!content) { + content = '{}'; + } + + try { + let contents = json.parse(content) || {}; + for (let key in contents) { + UserSettings.setNode(root, key, contents[key]); + } + + return c(UserSettings.doGetValue(root, key, fallback)); + } catch (error) { + return c(UserSettings.doGetValue(root, key, fallback)); // parse error + } + }); + }); + } + public get onChange(): EventProvider<(settings: ISettings) => void> { return this._onChange.value; } public getValue(key: string, fallback?: any): any { + return UserSettings.doGetValue(this.globalSettings.settings, key, fallback); + } + + private static doGetValue(globalSettings: any, key: string, fallback?: any): any { if (!key) { return fallback; } - let value = this.globalSettings.settings; + let value = globalSettings; let parts = key.split('\.'); while (parts.length && value) { @@ -77,7 +108,7 @@ export class UserSettings { this.timeoutHandle = global.setTimeout(() => { // Reload - let didChange = this.load(); + let didChange = this.loadSync(); // Emit event if (didChange) { @@ -87,8 +118,8 @@ export class UserSettings { }, UserSettings.CHANGE_BUFFER_DELAY); } - public load(): boolean { - let loadedSettings = this.doLoad(); + public loadSync(): boolean { + let loadedSettings = this.doLoadSync(); if (!objects.equals(loadedSettings, this.globalSettings)) { // Keep in class @@ -100,40 +131,17 @@ export class UserSettings { return false; // no changed value } - private doLoad(): ISettings { - let settings = this.doLoadSettings(); + private doLoadSync(): ISettings { + let settings = this.doLoadSettingsSync(); return { settings: settings.contents, settingsParseErrors: settings.parseErrors, - keybindings: this.doLoadKeybindings() + keybindings: this.doLoadKeybindingsSync() }; } - private doLoadSettings(): { contents: any; parseErrors?: string[]; } { - - function setNode(root: any, key: string, value: any): any { - let segments = key.split('.'); - let last = segments.pop(); - - let curr = root; - segments.forEach((s) => { - let obj = curr[s]; - switch (typeof obj) { - case 'undefined': - obj = curr[s] = {}; - break; - case 'object': - break; - default: - console.log('Conflicting user settings: ' + key + ' at ' + s + ' with ' + JSON.stringify(obj)); - } - curr = obj; - }); - curr[last] = value; - } - - + private doLoadSettingsSync(): { contents: any; parseErrors?: string[]; } { try { let root = {}; let content = '{}'; @@ -145,7 +153,7 @@ export class UserSettings { let contents = json.parse(content) || {}; for (let key in contents) { - setNode(root, key, contents[key]); + UserSettings.setNode(root, key, contents[key]); } return { contents: root @@ -159,7 +167,28 @@ export class UserSettings { } } - private doLoadKeybindings(): any { + private static setNode(root: any, key: string, value: any): any { + let segments = key.split('.'); + let last = segments.pop(); + + let curr = root; + segments.forEach((s) => { + let obj = curr[s]; + switch (typeof obj) { + case 'undefined': + obj = curr[s] = {}; + break; + case 'object': + break; + default: + console.log('Conflicting user settings: ' + key + ' at ' + s + ' with ' + JSON.stringify(obj)); + } + curr = obj; + }); + curr[last] = value; + } + + private doLoadKeybindingsSync(): any { try { return json.parse(fs.readFileSync(this.appKeybindingsPath).toString()); } catch (error) { diff --git a/src/vs/workbench/parts/extensions/node/extensionsService.ts b/src/vs/workbench/parts/extensions/node/extensionsService.ts index a9f88e7da6f..ebfc1657ca6 100644 --- a/src/vs/workbench/parts/extensions/node/extensionsService.ts +++ b/src/vs/workbench/parts/extensions/node/extensionsService.ts @@ -16,10 +16,11 @@ import { assign } from 'vs/base/common/objects'; import { extract, buffer } from 'vs/base/node/zip'; import { Promise, TPromise } from 'vs/base/common/winjs.base'; import { IExtensionsService, IExtension, IExtensionManifest, IGalleryInformation } from 'vs/workbench/parts/extensions/common/extensions'; -import { download } from 'vs/base/node/request'; +import { download, getProxyAgent, getSystemProxyAgent } from 'vs/base/node/request'; import { IWorkspaceContextService } from 'vs/workbench/services/workspace/common/contextService'; import { Limiter } from 'vs/base/common/async'; import Event, { Emitter } from 'vs/base/common/event'; +import { UserSettings } from 'vs/workbench/node/userSettings'; function parseManifest(raw: string): TPromise { return new Promise((c, e) => { @@ -120,15 +121,18 @@ export class ExtensionsService implements IExtensionsService { const extensionPath = path.join(this.extensionsPath, `${ extension.publisher }.${ extension.name }`); const manifestPath = path.join(extensionPath, 'package.json'); - return download(zipPath, { url }) - .then(() => validate(zipPath, extension)) - .then(manifest => { this._onInstallExtension.fire(manifest); return manifest; }) - .then(manifest => extract(zipPath, extensionPath, { sourcePath: 'extension', overwrite: true }).then(() => manifest)) - .then(manifest => { - manifest = assign({ __metadata: galleryInformation }, manifest); - return pfs.writeFile(manifestPath, JSON.stringify(manifest, null, '\t')); - }) - .then(() => { this._onDidInstallExtension.fire(extension); return extension; }); + return UserSettings.getValue(this.contextService, 'http.proxy').then((httpProxySettings) => { + const getAgent = url => httpProxySettings ? getProxyAgent(url, httpProxySettings) : getSystemProxyAgent(url); + return download(zipPath, { url: url, agent: getAgent(url) }) + .then(() => validate(zipPath, extension)) + .then(manifest => { this._onInstallExtension.fire(manifest); return manifest; }) + .then(manifest => extract(zipPath, extensionPath, { sourcePath: 'extension', overwrite: true }).then(() => manifest)) + .then(manifest => { + manifest = assign({ __metadata: galleryInformation }, manifest); + return pfs.writeFile(manifestPath, JSON.stringify(manifest, null, '\t')); + }) + .then(() => { this._onDidInstallExtension.fire(extension); return extension; }); + }); } private installFromZip(zipPath: string): TPromise {