mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-18 09:35:39 -05:00
Merge from vscode 3d67364fbfcf676d93be64f949e9b33e7f1b969e (#5028)
This commit is contained in:
@@ -3,11 +3,9 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { TernarySearchTree } from 'vs/base/common/map';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -16,7 +14,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, IEnvironment, MainThreadWindowShape, MainThreadTelemetryShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostContext, IInitData, IMainContext, MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostApiCommands } from 'vs/workbench/api/common/extHostApiCommands';
|
||||
import { ExtHostClipboard } from 'vs/workbench/api/common/extHostClipboard';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
@@ -47,7 +45,7 @@ import { LogOutputChannelFactory } from 'vs/workbench/api/node/extHostOutputServ
|
||||
import { ExtHostProgress } from 'vs/workbench/api/common/extHostProgress';
|
||||
import { ExtHostQuickOpen } from 'vs/workbench/api/common/extHostQuickOpen';
|
||||
import { ExtHostSCM } from 'vs/workbench/api/common/extHostSCM';
|
||||
import { ExtHostSearch } from 'vs/workbench/api/node/extHostSearch';
|
||||
import { ExtHostSearch, registerEHSearchProviders } from 'vs/workbench/api/node/extHostSearch';
|
||||
import { ExtHostStatusBar } from 'vs/workbench/api/common/extHostStatusBar';
|
||||
import { ExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
|
||||
import { ExtHostTask } from 'vs/workbench/api/node/extHostTask';
|
||||
@@ -60,7 +58,7 @@ import { ExtHostUrls } from 'vs/workbench/api/common/extHostUrls';
|
||||
import { ExtHostWebviews } from 'vs/workbench/api/common/extHostWebview';
|
||||
import { ExtHostWindow } from 'vs/workbench/api/common/extHostWindow';
|
||||
import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { throwProposedApiError, checkProposedApiEnabled, nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { throwProposedApiError, checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ProxyIdentifier } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
|
||||
import * as vscode from 'vscode';
|
||||
@@ -69,7 +67,7 @@ import { originalFSPath } from 'vs/base/common/resources';
|
||||
import { CLIServer } from 'vs/workbench/api/node/extHostCLIServer';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { values } from 'vs/base/common/collections';
|
||||
import { endsWith } from 'vs/base/common/strings';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
|
||||
export interface IExtensionApiFactory {
|
||||
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
|
||||
@@ -93,11 +91,11 @@ export function createApiFactory(
|
||||
extHostConfiguration: ExtHostConfiguration,
|
||||
extensionService: ExtHostExtensionService,
|
||||
extHostLogService: ExtHostLogService,
|
||||
extHostStorage: ExtHostStorage
|
||||
extHostStorage: ExtHostStorage,
|
||||
schemeTransformer: ISchemeTransformer | null,
|
||||
outputChannelName: string
|
||||
): IExtensionApiFactory {
|
||||
|
||||
const schemeTransformer: ISchemeTransformer | null = null;
|
||||
|
||||
// Addressable instances
|
||||
rpcProtocol.set(ExtHostContext.ExtHostLogService, extHostLogService);
|
||||
const extHostHeapService = rpcProtocol.set(ExtHostContext.ExtHostHeapService, new ExtHostHeapService());
|
||||
@@ -131,6 +129,14 @@ export function createApiFactory(
|
||||
const extHostOutputService = rpcProtocol.set(ExtHostContext.ExtHostOutputService, new ExtHostOutputService(LogOutputChannelFactory, initData.logsLocation, rpcProtocol));
|
||||
rpcProtocol.set(ExtHostContext.ExtHostStorage, extHostStorage);
|
||||
if (initData.remoteAuthority) {
|
||||
extHostTask.registerTaskSystem(Schemas.vscodeRemote, {
|
||||
scheme: Schemas.vscodeRemote,
|
||||
authority: initData.remoteAuthority,
|
||||
platform: process.platform
|
||||
});
|
||||
|
||||
registerEHSearchProviders(extHostSearch, extHostLogService);
|
||||
|
||||
const cliServer = new CLIServer(extHostCommands);
|
||||
process.env['VSCODE_IPC_HOOK_CLI'] = cliServer.ipcHandlePath;
|
||||
}
|
||||
@@ -147,8 +153,7 @@ export function createApiFactory(
|
||||
const extHostLanguages = new ExtHostLanguages(rpcProtocol, extHostDocuments);
|
||||
|
||||
// Register an output channel for exthost log
|
||||
const name = localize('extensionsLog', "Extension Host");
|
||||
extHostOutputService.createOutputChannelFromLogFile(name, extHostLogService.logFile);
|
||||
extHostOutputService.createOutputChannelFromLogFile(outputChannelName, extHostLogService.logFile);
|
||||
|
||||
// Register API-ish commands
|
||||
ExtHostApiCommands.register(extHostCommands);
|
||||
@@ -881,240 +886,3 @@ class Extension<T> implements vscode.Extension<T> {
|
||||
return this._extensionService.activateByIdWithErrors(this._identifier, new ExtensionActivatedByAPI(false)).then(() => this.exports);
|
||||
}
|
||||
}
|
||||
|
||||
interface LoadFunction {
|
||||
(request: string, parent: { filename: string; }, isMain: any): any;
|
||||
}
|
||||
|
||||
interface INodeModuleFactory {
|
||||
readonly nodeModuleName: string | string[];
|
||||
load(request: string, parent: { filename: string; }, isMain: any, original: LoadFunction): 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._alternatives = [];
|
||||
this._installInterceptor(this._factories, this._alternatives);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return factories.get(request)!.load(request, parent, isMain, original);
|
||||
};
|
||||
}
|
||||
|
||||
public register(interceptor: INodeModuleFactory): void {
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class VSCodeNodeModuleFactory implements INodeModuleFactory {
|
||||
public readonly nodeModuleName = 'vscode';
|
||||
|
||||
private readonly _extApiImpl = new Map<string, typeof vscode>();
|
||||
private _defaultApiImpl: typeof vscode;
|
||||
|
||||
constructor(
|
||||
private readonly _apiFactory: IExtensionApiFactory,
|
||||
private readonly _extensionPaths: TernarySearchTree<IExtensionDescription>,
|
||||
private readonly _extensionRegistry: ExtensionDescriptionRegistry,
|
||||
private readonly _configProvider: ExtHostConfigProvider
|
||||
) {
|
||||
}
|
||||
|
||||
public load(request: string, parent: { filename: string; }): any {
|
||||
|
||||
// get extension id from filename and api for extension
|
||||
const ext = this._extensionPaths.findSubstr(URI.file(parent.filename).fsPath);
|
||||
if (ext) {
|
||||
let apiImpl = this._extApiImpl.get(ExtensionIdentifier.toKey(ext.identifier));
|
||||
if (!apiImpl) {
|
||||
apiImpl = this._apiFactory(ext, this._extensionRegistry, this._configProvider);
|
||||
this._extApiImpl.set(ExtensionIdentifier.toKey(ext.identifier), apiImpl);
|
||||
}
|
||||
return apiImpl;
|
||||
}
|
||||
|
||||
// fall back to a default implementation
|
||||
if (!this._defaultApiImpl) {
|
||||
let extensionPathsPretty = '';
|
||||
this._extensionPaths.forEach((value, index) => extensionPathsPretty += `\t${index} -> ${value.identifier.value}\n`);
|
||||
console.warn(`Could not identify extension for 'vscode' require call from ${parent.filename}. These are the extension path mappings: \n${extensionPathsPretty}`);
|
||||
this._defaultApiImpl = this._apiFactory(nullExtensionDescription, this._extensionRegistry, this._configProvider);
|
||||
}
|
||||
return this._defaultApiImpl;
|
||||
}
|
||||
}
|
||||
|
||||
interface IKeytarModule {
|
||||
getPassword(service: string, account: string): Promise<string | null>;
|
||||
setPassword(service: string, account: string, password: string): Promise<void>;
|
||||
deletePassword(service: string, account: string): Promise<boolean>;
|
||||
findPassword(service: string): Promise<string | null>;
|
||||
}
|
||||
|
||||
export class KeytarNodeModuleFactory implements INodeModuleFactory {
|
||||
public readonly nodeModuleName: string = 'keytar';
|
||||
|
||||
private alternativeNames: Set<string> | undefined;
|
||||
private _impl: IKeytarModule;
|
||||
|
||||
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);
|
||||
},
|
||||
setPassword: (service: string, account: string, password: string): Promise<void> => {
|
||||
return mainThreadKeytar.$setPassword(service, account, password);
|
||||
},
|
||||
deletePassword: (service: string, account: string): Promise<boolean> => {
|
||||
return mainThreadKeytar.$deletePassword(service, account);
|
||||
},
|
||||
findPassword: (service: string): Promise<string | null> => {
|
||||
return mainThreadKeytar.$findPassword(service);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
const sep = length - 7;
|
||||
if ((name.charAt(sep) === '/' || name.charAt(sep) === '\\') && endsWith(name, 'keytar')) {
|
||||
name = name.replace(/\\/g, '/');
|
||||
if (this.alternativeNames.has(name)) {
|
||||
return 'keytar';
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
interface OpenOptions {
|
||||
wait: boolean;
|
||||
app: string | string[];
|
||||
}
|
||||
|
||||
interface IOriginalOpen {
|
||||
(target: string, options?: OpenOptions): Thenable<any>;
|
||||
}
|
||||
|
||||
interface IOpenModule {
|
||||
(target: string, options?: OpenOptions): Thenable<void>;
|
||||
}
|
||||
|
||||
export class OpenNodeModuleFactory implements INodeModuleFactory {
|
||||
|
||||
public readonly nodeModuleName: string[] = ['open', 'opn'];
|
||||
|
||||
private _extensionId: string | undefined;
|
||||
private _original: IOriginalOpen;
|
||||
private _impl: IOpenModule;
|
||||
|
||||
constructor(mainThreadWindow: MainThreadWindowShape, private _mainThreadTelemerty: MainThreadTelemetryShape, private readonly _extensionPaths: TernarySearchTree<IExtensionDescription>) {
|
||||
this._impl = (target, options) => {
|
||||
const uri: URI = URI.parse(target);
|
||||
// If we have options use the original method.
|
||||
if (options) {
|
||||
return this.callOriginal(target, options);
|
||||
}
|
||||
if (uri.scheme === 'http' || uri.scheme === 'https') {
|
||||
return mainThreadWindow.$openUri(uri);
|
||||
} else if (uri.scheme === 'mailto') {
|
||||
return mainThreadWindow.$openUri(uri);
|
||||
}
|
||||
return this.callOriginal(target, options);
|
||||
};
|
||||
}
|
||||
|
||||
public load(request: string, parent: { filename: string; }, isMain: any, original: LoadFunction): any {
|
||||
// get extension id from filename and api for extension
|
||||
const extension = this._extensionPaths.findSubstr(URI.file(parent.filename).fsPath);
|
||||
if (extension) {
|
||||
this._extensionId = extension.identifier.value;
|
||||
this.sendShimmingTelemetry();
|
||||
}
|
||||
|
||||
this._original = original(request, parent, isMain);
|
||||
return this._impl;
|
||||
}
|
||||
|
||||
private callOriginal(target: string, options: OpenOptions | undefined): Thenable<any> {
|
||||
this.sendNoForwardTelemetry();
|
||||
return this._original(target, options);
|
||||
}
|
||||
|
||||
private sendShimmingTelemetry(): void {
|
||||
if (!this._extensionId) {
|
||||
return;
|
||||
}
|
||||
/* __GDPR__
|
||||
"shimming.open" : {
|
||||
"extension": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
this._mainThreadTelemerty.$publicLog('shimming.open', { extension: this._extensionId });
|
||||
}
|
||||
|
||||
private sendNoForwardTelemetry(): void {
|
||||
if (!this._extensionId) {
|
||||
return;
|
||||
}
|
||||
/* __GDPR__
|
||||
"shimming.open.call.noForward" : {
|
||||
"extension": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
this._mainThreadTelemerty.$publicLog('shimming.open.call.noForward', { extension: this._extensionId });
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user