extHostAuthentication.ts 4.8 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import * as modes from 'vs/editor/common/modes';
import { Emitter, Event } from 'vs/base/common/event';
import { IMainContext, MainContext, MainThreadAuthenticationShape, ExtHostAuthenticationShape } from 'vs/workbench/api/common/extHost.protocol';
10 11
import { Disposable } from 'vs/workbench/api/common/extHostTypes';
import { IExtensionDescription, ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
12

13 14
export class AuthenticationProviderWrapper implements vscode.AuthenticationProvider {
	onDidChangeSessions: Event<void>;
15

16 17
	constructor(private _requestingExtension: IExtensionDescription,
		private _provider: vscode.AuthenticationProvider,
18
		private _proxy: MainThreadAuthenticationShape) {
19 20 21 22 23 24 25 26 27 28

		this.onDidChangeSessions = this._provider.onDidChangeSessions;
	}

	get id(): string {
		return this._provider.id;
	}

	get displayName(): string {
		return this._provider.displayName;
29 30
	}

31 32 33 34 35 36
	async getSessions(): Promise<ReadonlyArray<vscode.Session>> {
		const isAllowed = await this._proxy.$getSessionsPrompt(this._provider.id, this.displayName, ExtensionIdentifier.toKey(this._requestingExtension.identifier), this._requestingExtension.displayName || this._requestingExtension.name);
		if (!isAllowed) {
			throw new Error('User did not consent to session access.');
		}

37
		return this._provider.getSessions();
38 39
	}

40 41 42 43 44 45
	async login(): Promise<vscode.Session> {
		const isAllowed = await this._proxy.$loginPrompt(this._provider.id, this.displayName, ExtensionIdentifier.toKey(this._requestingExtension.identifier), this._requestingExtension.displayName || this._requestingExtension.name);
		if (!isAllowed) {
			throw new Error('User did not consent to login.');
		}

46 47 48
		return this._provider.login();
	}

49 50
	logout(sessionId: string): Promise<void> {
		return this._provider.logout(sessionId);
51 52 53 54 55
	}
}

export class ExtHostAuthentication implements ExtHostAuthenticationShape {
	private _proxy: MainThreadAuthenticationShape;
56
	private _authenticationProviders: Map<string, vscode.AuthenticationProvider> = new Map<string, vscode.AuthenticationProvider>();
57 58 59 60

	private _onDidRegisterAuthenticationProvider = new Emitter<string>();
	readonly onDidRegisterAuthenticationProvider: Event<string> = this._onDidRegisterAuthenticationProvider.event;

61 62
	private _onDidUnregisterAuthenticationProvider = new Emitter<string>();
	readonly onDidUnregisterAuthenticationProvider: Event<string> = this._onDidUnregisterAuthenticationProvider.event;
63 64 65

	constructor(mainContext: IMainContext) {
		this._proxy = mainContext.getProxy(MainContext.MainThreadAuthentication);
66
	}
67

68 69 70 71
	providers(requestingExtension: IExtensionDescription): vscode.AuthenticationProvider[] {
		let providers: vscode.AuthenticationProvider[] = [];
		this._authenticationProviders.forEach(provider => providers.push(new AuthenticationProviderWrapper(requestingExtension, provider, this._proxy)));
		return providers;
72
	}
73

74
	registerAuthenticationProvider(provider: vscode.AuthenticationProvider): vscode.Disposable {
75 76 77 78
		if (this._authenticationProviders.get(provider.id)) {
			throw new Error(`An authentication provider with id '${provider.id}' is already registered.`);
		}

79 80 81 82 83
		this._authenticationProviders.set(provider.id, provider);

		const listener = provider.onDidChangeSessions(_ => {
			this._proxy.$onDidChangeSessions(provider.id);
		});
84

85 86
		this._proxy.$registerAuthenticationProvider(provider.id);
		this._onDidRegisterAuthenticationProvider.fire(provider.id);
87 88 89 90 91 92 93

		return new Disposable(() => {
			listener.dispose();
			this._authenticationProviders.delete(provider.id);
			this._proxy.$unregisterAuthenticationProvider(provider.id);
			this._onDidUnregisterAuthenticationProvider.fire(provider.id);
		});
94 95
	}

96 97
	$login(providerId: string): Promise<modes.Session> {
		const authProvider = this._authenticationProviders.get(providerId);
98
		if (authProvider) {
99
			return Promise.resolve(authProvider.login());
100 101
		}

102
		throw new Error(`Unable to find authentication provider with handle: ${0}`);
103 104
	}

105 106
	$logout(providerId: string, sessionId: string): Promise<void> {
		const authProvider = this._authenticationProviders.get(providerId);
107
		if (authProvider) {
108
			return Promise.resolve(authProvider.logout(sessionId));
109 110
		}

111
		throw new Error(`Unable to find authentication provider with handle: ${0}`);
112 113
	}

114 115
	$getSessions(providerId: string): Promise<ReadonlyArray<modes.Session>> {
		const authProvider = this._authenticationProviders.get(providerId);
116
		if (authProvider) {
117
			return Promise.resolve(authProvider.getSessions());
118 119
		}

120
		throw new Error(`Unable to find authentication provider with handle: ${0}`);
121 122
	}
}