diff --git a/src/vs/code/browser/workbench/workbench-dev.html b/src/vs/code/browser/workbench/workbench-dev.html index 0142bb7f53d..992fead7e94 100644 --- a/src/vs/code/browser/workbench/workbench-dev.html +++ b/src/vs/code/browser/workbench/workbench-dev.html @@ -14,12 +14,12 @@ + + + - - - diff --git a/src/vs/code/browser/workbench/workbench.html b/src/vs/code/browser/workbench/workbench.html index d56e3fdd36a..b4f0ef89ce1 100644 --- a/src/vs/code/browser/workbench/workbench.html +++ b/src/vs/code/browser/workbench/workbench.html @@ -14,6 +14,9 @@ + + + diff --git a/src/vs/code/browser/workbench/workbench.ts b/src/vs/code/browser/workbench/workbench.ts index 9b814729d31..39bba698acb 100644 --- a/src/vs/code/browser/workbench/workbench.ts +++ b/src/vs/code/browser/workbench/workbench.ts @@ -17,6 +17,24 @@ import { isStandalone } from 'vs/base/browser/browser'; import { localize } from 'vs/nls'; import { Schemas } from 'vs/base/common/network'; +function doCreateUri(path: string, queryValues: Map): URI { + let query: string | undefined = undefined; + + if (queryValues) { + let index = 0; + queryValues.forEach((value, key) => { + if (!query) { + query = ''; + } + + const prefix = (index++ === 0) ? '' : '&'; + query += `${prefix}${key}=${encodeURIComponent(value)}`; + }); + } + + return URI.parse(window.location.href).with({ path, query }); +} + interface ICredential { service: string; account: string; @@ -68,7 +86,7 @@ class LocalStorageCredentialsProvider implements ICredentialsProvider { } async setPassword(service: string, account: string, password: string): Promise { - this.deletePassword(service, account); + this.doDeletePassword(service, account); this.credentials.push({ service, account, password }); @@ -76,6 +94,22 @@ class LocalStorageCredentialsProvider implements ICredentialsProvider { } async deletePassword(service: string, account: string): Promise { + const result = await this.doDeletePassword(service, account); + + if (result) { + const queryValues: Map = new Map(); + queryValues.set('logout', String(true)); + queryValues.set('service', service); + + await request({ + url: doCreateUri('/auth/logout', queryValues).toString(true) + }, CancellationToken.None); + } + + return result; + } + + async doDeletePassword(service: string, account: string): Promise { let found = false; this._credentials = this.credentials.filter(credential => { @@ -154,7 +188,7 @@ class PollingURLCallbackProvider extends Disposable implements IURLCallbackProvi // Start to poll on the callback being fired this.periodicFetchCallback(requestId, Date.now()); - return this.doCreateUri('/callback', queryValues); + return doCreateUri('/callback', queryValues); } private async periodicFetchCallback(requestId: string, startTime: number): Promise { @@ -164,7 +198,7 @@ class PollingURLCallbackProvider extends Disposable implements IURLCallbackProvi queryValues.set(PollingURLCallbackProvider.QUERY_KEYS.REQUEST_ID, requestId); const result = await request({ - url: this.doCreateUri('/fetch-callback', queryValues).toString(true) + url: doCreateUri('/fetch-callback', queryValues).toString(true) }, CancellationToken.None); // Check for callback results @@ -185,23 +219,6 @@ class PollingURLCallbackProvider extends Disposable implements IURLCallbackProvi } } - private doCreateUri(path: string, queryValues: Map): URI { - let query: string | undefined = undefined; - - if (queryValues) { - let index = 0; - queryValues.forEach((value, key) => { - if (!query) { - query = ''; - } - - const prefix = (index++ === 0) ? '' : '&'; - query += `${prefix}${key}=${encodeURIComponent(value)}`; - }); - } - - return URI.parse(window.location.href).with({ path, query }); - } } class WorkspaceProvider implements IWorkspaceProvider { diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 34184c32e0c..6b079117b33 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -200,7 +200,10 @@ export class AccountsActionViewItem extends ActivityActionViewItem { return this.authenticationService.signOutOfAccount(sessionInfo.providerId, accountName); }); - const actions = hasEmbedderAccountSession ? [manageExtensionsAction] : [manageExtensionsAction, signOutAction]; + const actions = [manageExtensionsAction]; + if (!hasEmbedderAccountSession || authenticationSession?.canSignOut) { + actions.push(signOutAction); + } const menu = new SubmenuAction('activitybar.submenu', `${accountName} (${providerDisplayName})`, actions); menus.push(menu); diff --git a/src/vs/workbench/services/authentication/browser/authenticationService.ts b/src/vs/workbench/services/authentication/browser/authenticationService.ts index db85f09a426..59f88d7cebf 100644 --- a/src/vs/workbench/services/authentication/browser/authenticationService.ts +++ b/src/vs/workbench/services/authentication/browser/authenticationService.ts @@ -26,7 +26,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten export function getAuthenticationProviderActivationEvent(id: string): string { return `onAuthenticationRequest:${id}`; } -export type AuthenticationSessionInfo = { readonly id: string, readonly accessToken: string, readonly providerId: string }; +export type AuthenticationSessionInfo = { readonly id: string, readonly accessToken: string, readonly providerId: string, readonly canSignOut?: boolean }; export async function getCurrentAuthenticationSessionInfo(environmentService: IWorkbenchEnvironmentService, productService: IProductService): Promise { if (environmentService.options?.credentialsProvider) { const authenticationSessionValue = await environmentService.options.credentialsProvider.getPassword(`${productService.urlProtocol}.login`, 'account');