Prevent other extensions registering terminal profiles

This commit is contained in:
Daniel Imms 2021-06-11 06:45:36 -07:00
parent 9677eddbff
commit 465759bc58
8 changed files with 30 additions and 22 deletions

View file

@ -211,10 +211,12 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
this._terminalService.registerProcessSupport(isSupported);
}
public $registerProfileProvider(id: string): void {
public $registerProfileProvider(id: string, extensionIdentifier: string): void {
// Proxy profile provider requests through the extension host
this._profileProviders.set(id, this._terminalService.registerTerminalProfileProvider(id, {
createContributedTerminalProfile: async (isSplitTerminal) => this._proxy.$createContributedProfileTerminal(id, isSplitTerminal)
this._profileProviders.set(id, this._terminalService.registerTerminalProfileProvider(extensionIdentifier, id, {
createContributedTerminalProfile: async (isSplitTerminal) => {
return this._proxy.$createContributedProfileTerminal(id, isSplitTerminal);
}
}));
}

View file

@ -675,7 +675,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostTerminalService.registerLinkProvider(provider);
},
registerTerminalProfileProvider(id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable {
return extHostTerminalService.registerProfileProvider(id, provider);
return extHostTerminalService.registerProfileProvider(extension, id, provider);
},
registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider<any>): vscode.Disposable {
return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider, extension);

View file

@ -486,7 +486,7 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
$startLinkProvider(): void;
$stopLinkProvider(): void;
$registerProcessSupport(isSupported: boolean): void;
$registerProfileProvider(id: string): void;
$registerProfileProvider(id: string, extensionIdentifier: string): void;
$unregisterProfileProvider(id: string): void;
$setEnvironmentVariableCollection(extensionIdentifier: string, persistent: boolean, collection: ISerializableEnvironmentVariableCollection | undefined): void;

View file

@ -43,7 +43,7 @@ export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, ID
getDefaultShell(useAutomationShell: boolean): string;
getDefaultShellArgs(useAutomationShell: boolean): string[] | string;
registerLinkProvider(provider: vscode.TerminalLinkProvider): vscode.Disposable;
registerProfileProvider(id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable;
registerProfileProvider(extension: IExtensionDescription, id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable;
getEnvironmentVariableCollection(extension: IExtensionDescription, persistent?: boolean): vscode.EnvironmentVariableCollection;
}
@ -584,12 +584,12 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
});
}
public registerProfileProvider(id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable {
public registerProfileProvider(extension: IExtensionDescription, id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable {
if (this._profileProviders.has(id)) {
throw new Error(`Terminal profile provider "${id}" already registered`);
}
this._profileProviders.set(id, provider);
this._proxy.$registerProfileProvider(id);
this._proxy.$registerProfileProvider(id, extension.identifier.value);
return new VSCodeDisposable(() => {
this._profileProviders.delete(id);
this._proxy.$unregisterProfileProvider(id);

View file

@ -141,7 +141,7 @@ export interface ITerminalService {
*/
createTerminal(profile: ITerminalProfile): ITerminalInstance;
createContributedTerminalProfile(id: string, isSplitTerminal: boolean): Promise<void>;
createContributedTerminalProfile(extensionIdentifier: string, id: string, isSplitTerminal: boolean): Promise<void>;
/**
* Creates a raw terminal instance, this should not be used outside of the terminal part.
@ -201,7 +201,7 @@ export interface ITerminalService {
*/
registerLinkProvider(linkProvider: ITerminalExternalLinkProvider): IDisposable;
registerTerminalProfileProvider(id: string, profileProvider: ITerminalProfileProvider): IDisposable;
registerTerminalProfileProvider(extensionIdenfifier: string, id: string, profileProvider: ITerminalProfileProvider): IDisposable;
showProfileQuickPick(type: 'setDefault' | 'createInstance', cwd?: string | URI): Promise<ITerminalInstance | undefined>;

View file

@ -57,7 +57,7 @@ export class TerminalService implements ITerminalService {
private _findState: FindReplaceState;
private _activeGroupIndex: number;
private _activeInstanceIndex: number;
private readonly _profileProviders: Map<string, ITerminalProfileProvider> = new Map();
private readonly _profileProviders: Map</*ext id*/string, Map</*provider id*/string, ITerminalProfileProvider>> = new Map();
private _linkProviders: Set<ITerminalExternalLinkProvider> = new Set();
private _linkProviderDisposables: Map<ITerminalExternalLinkProvider, IDisposable[]> = new Map();
private _processSupportContextKey: IContextKey<boolean>;
@ -811,8 +811,13 @@ export class TerminalService implements ITerminalService {
};
}
registerTerminalProfileProvider(id: string, profileProvider: ITerminalProfileProvider): IDisposable {
this._profileProviders.set(id, profileProvider);
registerTerminalProfileProvider(extensionIdenfifier: string, id: string, profileProvider: ITerminalProfileProvider): IDisposable {
let extMap = this._profileProviders.get(extensionIdenfifier);
if (!extMap) {
extMap = new Map();
this._profileProviders.set(extensionIdenfifier, extMap);
}
extMap.set(id, profileProvider);
return toDisposable(() => this._profileProviders.delete(id));
}
@ -976,7 +981,7 @@ export class TerminalService implements ITerminalService {
let instance;
if ('id' in value.profile) {
await this.createContributedTerminalProfile(value.profile.id, !!(keyMods?.alt && activeInstance));
await this.createContributedTerminalProfile(value.profile.extensionIdentifier, value.profile.id, !!(keyMods?.alt && activeInstance));
return;
} else {
if (keyMods?.alt && activeInstance) {
@ -1017,9 +1022,10 @@ export class TerminalService implements ITerminalService {
return undefined;
}
async createContributedTerminalProfile(id: string, isSplitTerminal: boolean): Promise<void> {
async createContributedTerminalProfile(extensionIdentifier: string, id: string, isSplitTerminal: boolean): Promise<void> {
await this._extensionService.activateByEvent(`onTerminalProfile:${id}`);
const profileProvider = this._profileProviders.get(id);
const extMap = this._profileProviders.get(extensionIdentifier);
const profileProvider = extMap?.get(id);
if (!profileProvider) {
this._notificationService.error(`No terminal profile provider registered for id "${id}"`);
return;
@ -1207,7 +1213,7 @@ export class TerminalService implements ITerminalService {
}
interface IProfileQuickPickItem extends IQuickPickItem {
profile: ITerminalProfile | ITerminalProfileContribution;
profile: ITerminalProfile | (ITerminalProfileContribution & { extensionIdentifier: string });
}
interface IInstanceLocation {

View file

@ -227,8 +227,8 @@ export class TerminalViewPane extends ViewPane {
}
for (const contributed of this._terminalContributionService.terminalProfiles) {
dropdownActions.push(new Action(TerminalCommandId.NewWithProfile, contributed.title, undefined, true, () => this._terminalService.createContributedTerminalProfile(contributed.id, false)));
submenuActions.push(new Action(TerminalCommandId.NewWithProfile, contributed.title, undefined, true, () => this._terminalService.createContributedTerminalProfile(contributed.id, true)));
dropdownActions.push(new Action(TerminalCommandId.NewWithProfile, contributed.title, undefined, true, () => this._terminalService.createContributedTerminalProfile(contributed.extensionIdentifier, contributed.id, false)));
submenuActions.push(new Action(TerminalCommandId.NewWithProfile, contributed.title, undefined, true, () => this._terminalService.createContributedTerminalProfile(contributed.extensionIdentifier, contributed.id, true)));
}
if (dropdownActions.length > 0) {

View file

@ -14,7 +14,7 @@ export const terminalsExtPoint = extensionsRegistry.ExtensionsRegistry.registerE
export interface ITerminalContributionService {
readonly _serviceBrand: undefined;
readonly terminalProfiles: ReadonlyArray<ITerminalProfileContribution>;
readonly terminalProfiles: ReadonlyArray<ITerminalProfileContribution & { extensionIdentifier: string }>;
}
export const ITerminalContributionService = createDecorator<ITerminalContributionService>('terminalContributionsService');
@ -22,7 +22,7 @@ export const ITerminalContributionService = createDecorator<ITerminalContributio
export class TerminalContributionService implements ITerminalContributionService {
declare _serviceBrand: undefined;
private _terminalProfiles: ReadonlyArray<ITerminalProfileContribution> = [];
private _terminalProfiles: ReadonlyArray<ITerminalProfileContribution & { extensionIdentifier: string }> = [];
get terminalProfiles() { return this._terminalProfiles; }
constructor() {
@ -36,7 +36,7 @@ export class TerminalContributionService implements ITerminalContributionService
} else {
e.icon = undefined;
}
return e;
return { ...e, extensionIdentifier: c.description.identifier.value };
}) || [];
}));
});