diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts index 5d09864595c..b610fc9ad73 100644 --- a/src/vs/workbench/api/node/extHostExtensionService.ts +++ b/src/vs/workbench/api/node/extHostExtensionService.ts @@ -6,6 +6,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import * as paths from 'vs/base/common/paths'; +import { mkdirp, dirExists } from 'vs/base/node/pfs'; import Severity from 'vs/base/common/severity'; import { TPromise } from 'vs/base/common/winjs.base'; import { AbstractExtensionService, ActivatedExtension } from 'vs/platform/extensions/common/abstractExtensionService'; @@ -13,7 +14,9 @@ import { IExtensionDescription } from 'vs/platform/extensions/common/extensions' import { ExtHostStorage } from 'vs/workbench/api/node/extHostStorage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThreadService } from 'vs/workbench/services/thread/common/threadService'; -import { MainContext, MainProcessExtensionServiceShape } from './extHost.protocol'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { MainContext, MainProcessExtensionServiceShape, IEnvironment } from './extHost.protocol'; +import { createHash } from 'crypto'; const hasOwnProperty = Object.hasOwnProperty; @@ -97,6 +100,57 @@ class ExtensionMemento implements IExtensionMemento { } } +class ExtensionStoragePath { + + private readonly _contextService: IWorkspaceContextService; + private readonly _environment: IEnvironment; + + private readonly _ready: TPromise; + private _value: string; + + constructor(contextService: IWorkspaceContextService, environment: IEnvironment) { + this._contextService = contextService; + this._environment = environment; + this._ready = this._getOrCreateWorkspaceStoragePath().then(value => this._value = value); + } + + get whenReady(): TPromise { + return this._ready; + } + + get value(): string { + return this._value; + } + + private _getOrCreateWorkspaceStoragePath(): TPromise { + + const workspace = this._contextService.getWorkspace(); + + if (!workspace) { + return TPromise.as(undefined); + } + + const storageName = createHash('md5') + .update(workspace.resource.fsPath) + .update(workspace.uid ? workspace.uid.toString() : '') + .digest('hex'); + + const storagePath = paths.join(this._environment.appSettingsHome, 'workspaceStorage', storageName); + + return dirExists(storagePath).then(exists => { + if (exists) { + return storagePath; + } + + mkdirp(storagePath).then(success => { + return storagePath; + }, err => { + return undefined; + }); + }); + } +} + export interface IExtensionContext { subscriptions: IDisposable[]; workspaceState: IExtensionMemento; @@ -110,21 +164,23 @@ export class ExtHostExtensionService extends AbstractExtensionService { + return TPromise.join([ + globalState.whenReady, + workspaceState.whenReady, + this._storagePath.whenReady + ]).then(() => { return Object.freeze({ globalState, workspaceState, subscriptions: [], get extensionPath() { return extensionDescription.extensionFolderPath; }, - storagePath: storagePath, + storagePath: paths.join(this._storagePath.value, extensionDescription.id), asAbsolutePath: (relativePath: string) => { return paths.normalize(paths.join(extensionDescription.extensionFolderPath, relativePath), true); } }); }); diff --git a/src/vs/workbench/node/extensionHostMain.ts b/src/vs/workbench/node/extensionHostMain.ts index b8b3d1c12e2..d2e762b88f9 100644 --- a/src/vs/workbench/node/extensionHostMain.ts +++ b/src/vs/workbench/node/extensionHostMain.ts @@ -5,8 +5,6 @@ 'use strict'; -import * as fs from 'fs'; -import * as crypto from 'crypto'; import nls = require('vs/nls'); import pfs = require('vs/base/node/pfs'); import { TPromise } from 'vs/base/common/winjs.base'; @@ -35,25 +33,19 @@ interface ITestRunner { export class ExtensionHostMain { - private _isTerminating: boolean; + private _isTerminating: boolean = false; private _contextService: IWorkspaceContextService; private _environment: IEnvironment; private _extensionService: ExtHostExtensionService; private _extensionApiCreation: TPromise; constructor(remoteCom: IMainProcessExtHostIPC, initData: IInitData) { - this._isTerminating = false; - + // services this._environment = initData.environment; - this._contextService = new WorkspaceContextService(initData.contextService.workspace); - const workspaceStoragePath = this._getOrCreateWorkspaceStoragePath(); - const threadService = new ExtHostThreadService(remoteCom); - const telemetryService = new RemoteTelemetryService('pluginHostTelemetry', threadService); - - this._extensionService = new ExtHostExtensionService(initData.extensions, threadService, telemetryService, { _serviceBrand: 'optionalArgs', workspaceStoragePath }); + this._extensionService = new ExtHostExtensionService(initData.extensions, initData.environment, threadService, telemetryService, this._contextService); // Error forwarding const mainThreadErrors = threadService.get(MainContext.MainThreadErrors); @@ -64,53 +56,6 @@ export class ExtensionHostMain { this._extensionApiCreation = initializeExtensionApi(this._extensionService, apiFactory); } - private _getOrCreateWorkspaceStoragePath(): string { - let workspaceStoragePath: string; - - const workspace = this._contextService.getWorkspace(); - - function rmkDir(directory: string): boolean { - try { - fs.mkdirSync(directory); - return true; - } catch (err) { - if (err.code === 'ENOENT') { - if (rmkDir(paths.dirname(directory))) { - fs.mkdirSync(directory); - return true; - } - } else { - return fs.statSync(directory).isDirectory(); - } - } - } - - if (workspace) { - const hash = crypto.createHash('md5'); - hash.update(workspace.resource.fsPath); - if (workspace.uid) { - hash.update(workspace.uid.toString()); - } - workspaceStoragePath = paths.join(this._environment.appSettingsHome, 'workspaceStorage', hash.digest('hex')); - if (!fs.existsSync(workspaceStoragePath)) { - try { - if (rmkDir(workspaceStoragePath)) { - fs.writeFileSync(paths.join(workspaceStoragePath, 'meta.json'), JSON.stringify({ - workspacePath: workspace.resource.fsPath, - uid: workspace.uid ? workspace.uid : null - }, null, 4)); - } else { - workspaceStoragePath = undefined; - } - } catch (err) { - workspaceStoragePath = undefined; - } - } - } - - return workspaceStoragePath; - } - public start(): TPromise { return this._extensionApiCreation .then(() => this.handleEagerExtensions())