mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-24 02:28:34 +01:00
Better Keytar shim
This commit is contained in:
@@ -16,7 +16,7 @@ import { OverviewRulerLane } from 'vs/editor/common/model';
|
||||
import * as languageConfiguration from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { score } from 'vs/editor/common/modes/languageSelector';
|
||||
import * as files from 'vs/platform/files/common/files';
|
||||
import { ExtHostContext, IInitData, IMainContext, MainContext, MainThreadKeytarShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostContext, IInitData, IMainContext, MainContext, MainThreadKeytarShape, IEnvironment } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostApiCommands } from 'vs/workbench/api/node/extHostApiCommands';
|
||||
import { ExtHostClipboard } from 'vs/workbench/api/node/extHostClipboard';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
|
||||
@@ -872,24 +872,34 @@ class Extension<T> implements vscode.Extension<T> {
|
||||
}
|
||||
|
||||
interface INodeModuleFactory {
|
||||
readonly nodeModuleName: string;
|
||||
readonly nodeModuleName: string | string[];
|
||||
load(request: string, parent: { filename: string; }): any;
|
||||
alternaiveModuleName?(name: string): string | undefined;
|
||||
}
|
||||
|
||||
export class NodeModuleRequireInterceptor {
|
||||
public static INSTANCE = new NodeModuleRequireInterceptor();
|
||||
|
||||
private readonly _factories: Map<string, INodeModuleFactory>;
|
||||
private readonly _alternatives: ((moduleName: string) => string | undefined)[];
|
||||
|
||||
constructor() {
|
||||
this._factories = new Map<string, INodeModuleFactory>();
|
||||
this._installInterceptor(this._factories);
|
||||
this._alternatives = [];
|
||||
this._installInterceptor(this._factories, this._alternatives);
|
||||
}
|
||||
|
||||
private _installInterceptor(factories: Map<string, INodeModuleFactory>): void {
|
||||
private _installInterceptor(factories: Map<string, INodeModuleFactory>, alternatives: ((moduleName: string) => string | undefined)[]): void {
|
||||
const node_module = <any>require.__$__nodeRequire('module');
|
||||
const original = node_module._load;
|
||||
node_module._load = function load(request: string, parent: { filename: string; }, isMain: any) {
|
||||
for (let alternativeModuleName of alternatives) {
|
||||
let alternative = alternativeModuleName(request);
|
||||
if (alternative) {
|
||||
request = alternative;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!factories.has(request)) {
|
||||
return original.apply(this, arguments);
|
||||
}
|
||||
@@ -898,7 +908,18 @@ export class NodeModuleRequireInterceptor {
|
||||
}
|
||||
|
||||
public register(interceptor: INodeModuleFactory): void {
|
||||
this._factories.set(interceptor.nodeModuleName, interceptor);
|
||||
if (Array.isArray(interceptor.nodeModuleName)) {
|
||||
for (let moduleName of interceptor.nodeModuleName) {
|
||||
this._factories.set(moduleName, interceptor);
|
||||
}
|
||||
} else {
|
||||
this._factories.set(interceptor.nodeModuleName, interceptor);
|
||||
}
|
||||
if (typeof interceptor.alternaiveModuleName === 'function') {
|
||||
this._alternatives.push((moduleName) => {
|
||||
return interceptor.alternaiveModuleName!(moduleName);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -948,11 +969,25 @@ interface IKeytarModule {
|
||||
}
|
||||
|
||||
export class KeytarNodeModuleFactory implements INodeModuleFactory {
|
||||
public readonly nodeModuleName = 'keytar';
|
||||
public readonly nodeModuleName: string = 'keytar';
|
||||
|
||||
private alternativeNames: Set<string> | undefined;
|
||||
private _impl: IKeytarModule;
|
||||
|
||||
constructor(mainThreadKeytar: MainThreadKeytarShape) {
|
||||
|
||||
constructor(mainThreadKeytar: MainThreadKeytarShape, environment: IEnvironment) {
|
||||
if (environment.appRoot) {
|
||||
let appRoot = environment.appRoot.fsPath;
|
||||
if (process.platform === 'win32') {
|
||||
appRoot = appRoot.replace(/\\/g, '/');
|
||||
}
|
||||
if (appRoot[appRoot.length - 1] === '/') {
|
||||
appRoot = appRoot.substr(0, appRoot.length - 1);
|
||||
}
|
||||
this.alternativeNames = new Set();
|
||||
this.alternativeNames.add(`${appRoot}/node_modules.asar/keytar`);
|
||||
this.alternativeNames.add(`${appRoot}/node_modules/keytar`);
|
||||
}
|
||||
this._impl = {
|
||||
getPassword: (service: string, account: string): Promise<string | null> => {
|
||||
return mainThreadKeytar.$getPassword(service, account);
|
||||
@@ -972,4 +1007,20 @@ export class KeytarNodeModuleFactory implements INodeModuleFactory {
|
||||
public load(request: string, parent: { filename: string; }): any {
|
||||
return this._impl;
|
||||
}
|
||||
|
||||
public alternaiveModuleName(name: string): string | undefined {
|
||||
const length = name.length;
|
||||
// We need at least something like: `?/keytar` which requires
|
||||
// more than 7 characters.
|
||||
if (length <= 7 || !this.alternativeNames) {
|
||||
return undefined;
|
||||
}
|
||||
if (name.match(/[\\\/]keytar$/)) {
|
||||
name = name.replace(/\\/g, '/');
|
||||
if (this.alternativeNames.has(name)) {
|
||||
return 'keytar';
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +161,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
private readonly _extHostContext: IMainContext;
|
||||
private readonly _extHostWorkspace: ExtHostWorkspace;
|
||||
private readonly _extHostConfiguration: ExtHostConfiguration;
|
||||
private readonly _environment: IEnvironment;
|
||||
private readonly _extHostLogService: ExtHostLogService;
|
||||
|
||||
private readonly _mainThreadWorkspaceProxy: MainThreadWorkspaceShape;
|
||||
@@ -186,6 +187,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
extHostContext: IMainContext,
|
||||
extHostWorkspace: ExtHostWorkspace,
|
||||
extHostConfiguration: ExtHostConfiguration,
|
||||
environment: IEnvironment,
|
||||
extHostLogService: ExtHostLogService
|
||||
) {
|
||||
this._nativeExit = nativeExit;
|
||||
@@ -193,6 +195,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
this._extHostContext = extHostContext;
|
||||
this._extHostWorkspace = extHostWorkspace;
|
||||
this._extHostConfiguration = extHostConfiguration;
|
||||
this._environment = environment;
|
||||
this._extHostLogService = extHostLogService;
|
||||
|
||||
this._mainThreadWorkspaceProxy = this._extHostContext.getProxy(MainContext.MainThreadWorkspace);
|
||||
@@ -244,7 +247,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
const configProvider = await this._extHostConfiguration.getConfigProvider();
|
||||
const extensionPaths = await this.getExtensionPathIndex();
|
||||
NodeModuleRequireInterceptor.INSTANCE.register(new VSCodeNodeModuleFactory(this._extensionApiFactory, extensionPaths, this._registry, configProvider));
|
||||
NodeModuleRequireInterceptor.INSTANCE.register(new KeytarNodeModuleFactory(this._extHostContext.getProxy(MainContext.MainThreadKeytar)));
|
||||
NodeModuleRequireInterceptor.INSTANCE.register(new KeytarNodeModuleFactory(this._extHostContext.getProxy(MainContext.MainThreadKeytar), this._environment));
|
||||
|
||||
// Do this when extension service exists, but extensions are not being activated yet.
|
||||
await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._extHostLogService, this._mainThreadTelemetryProxy);
|
||||
|
||||
Reference in New Issue
Block a user