提交 a27c9fc6 编写于 作者: S Sandeep Somavarapu

Fix #85211

上级 ad063b9d
......@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IUserData, UserDataSyncStoreError, UserDataSyncStoreErrorCode, SyncStatus, IUserDataSyncStoreService, ISyncExtension, IUserDataSyncLogService, IUserDataSynchroniser, SyncSource } from 'vs/platform/userDataSync/common/userDataSync';
import { IUserData, UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, ISyncExtension, IUserDataSyncLogService, IUserDataSynchroniser, SyncSource } from 'vs/platform/userDataSync/common/userDataSync';
import { VSBuffer } from 'vs/base/common/buffer';
import { Emitter, Event } from 'vs/base/common/event';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
......@@ -154,7 +154,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
await this.apply(previewResult);
} catch (e) {
this.setStatus(SyncStatus.Idle);
if (e instanceof UserDataSyncStoreError && e.code === UserDataSyncStoreErrorCode.Rejected) {
if (e instanceof UserDataSyncError && e.code === UserDataSyncErrorCode.Rejected) {
// Rejected as there is a new remote version. Syncing again,
this.logService.info('Extensions: Failed to synchronise extensions as there is a new remote version available. Synchronizing again...');
return this.sync();
......@@ -345,12 +345,12 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
}
private getRemoteUserData(lastSyncData?: IUserData | null): Promise<IUserData> {
return this.userDataSyncStoreService.read(ExtensionsSynchroniser.EXTERNAL_USER_DATA_EXTENSIONS_KEY, lastSyncData || null);
return this.userDataSyncStoreService.read(ExtensionsSynchroniser.EXTERNAL_USER_DATA_EXTENSIONS_KEY, lastSyncData || null, this.source);
}
private async writeToRemote(extensions: ISyncExtension[], ref: string | null): Promise<IUserData> {
const content = JSON.stringify(extensions);
ref = await this.userDataSyncStoreService.write(ExtensionsSynchroniser.EXTERNAL_USER_DATA_EXTENSIONS_KEY, content, ref);
ref = await this.userDataSyncStoreService.write(ExtensionsSynchroniser.EXTERNAL_USER_DATA_EXTENSIONS_KEY, content, ref, this.source);
return { content, ref };
}
......
......@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IUserData, UserDataSyncStoreError, UserDataSyncStoreErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IGlobalState, SyncSource, IUserDataSynchroniser } from 'vs/platform/userDataSync/common/userDataSync';
import { IUserData, UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IGlobalState, SyncSource, IUserDataSynchroniser } from 'vs/platform/userDataSync/common/userDataSync';
import { VSBuffer } from 'vs/base/common/buffer';
import { Emitter, Event } from 'vs/base/common/event';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
......@@ -132,7 +132,7 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs
this.logService.trace('UI State: Finished synchronizing ui state.');
} catch (e) {
this.setStatus(SyncStatus.Idle);
if (e instanceof UserDataSyncStoreError && e.code === UserDataSyncStoreErrorCode.Rejected) {
if (e instanceof UserDataSyncError && e.code === UserDataSyncErrorCode.Rejected) {
// Rejected as there is a new remote version. Syncing again,
this.logService.info('UI State: Failed to synchronise ui state as there is a new remote version available. Synchronizing again...');
return this.sync();
......@@ -259,12 +259,12 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs
}
private getRemoteUserData(lastSyncData?: IUserData | null): Promise<IUserData> {
return this.userDataSyncStoreService.read(GlobalStateSynchroniser.EXTERNAL_USER_DATA_GLOBAL_STATE_KEY, lastSyncData || null);
return this.userDataSyncStoreService.read(GlobalStateSynchroniser.EXTERNAL_USER_DATA_GLOBAL_STATE_KEY, lastSyncData || null, this.source);
}
private async writeToRemote(globalState: IGlobalState, ref: string | null): Promise<IUserData> {
const content = JSON.stringify(globalState);
ref = await this.userDataSyncStoreService.write(GlobalStateSynchroniser.EXTERNAL_USER_DATA_GLOBAL_STATE_KEY, content, ref);
ref = await this.userDataSyncStoreService.write(GlobalStateSynchroniser.EXTERNAL_USER_DATA_GLOBAL_STATE_KEY, content, ref, this.source);
return { content, ref };
}
......
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IFileService, FileSystemProviderErrorCode, FileSystemProviderError, IFileContent, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files';
import { IUserData, UserDataSyncStoreError, UserDataSyncStoreErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService, SyncSource, IUserDataSynchroniser } from 'vs/platform/userDataSync/common/userDataSync';
import { IUserData, UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService, SyncSource, IUserDataSynchroniser } from 'vs/platform/userDataSync/common/userDataSync';
import { merge } from 'vs/platform/userDataSync/common/keybindingsMerge';
import { VSBuffer } from 'vs/base/common/buffer';
import { parse, ParseError } from 'vs/base/common/json';
......@@ -266,7 +266,7 @@ export class KeybindingsSynchroniser extends AbstractSynchroniser implements IUs
} catch (e) {
this.syncPreviewResultPromise = null;
this.setStatus(SyncStatus.Idle);
if (e instanceof UserDataSyncStoreError && e.code === UserDataSyncStoreErrorCode.Rejected) {
if (e instanceof UserDataSyncError && e.code === UserDataSyncErrorCode.Rejected) {
// Rejected as there is a new remote version. Syncing again,
this.logService.info('Keybindings: Failed to synchronise keybindings as there is a new remote version available. Synchronizing again...');
return this.sync();
......@@ -433,11 +433,11 @@ export class KeybindingsSynchroniser extends AbstractSynchroniser implements IUs
}
private async getRemoteUserData(lastSyncData?: IUserData | null): Promise<IUserData> {
return this.userDataSyncStoreService.read(KeybindingsSynchroniser.EXTERNAL_USER_DATA_KEYBINDINGS_KEY, lastSyncData || null);
return this.userDataSyncStoreService.read(KeybindingsSynchroniser.EXTERNAL_USER_DATA_KEYBINDINGS_KEY, lastSyncData || null, this.source);
}
private async updateRemoteUserData(content: string, ref: string | null): Promise<string> {
return this.userDataSyncStoreService.write(KeybindingsSynchroniser.EXTERNAL_USER_DATA_KEYBINDINGS_KEY, content, ref);
return this.userDataSyncStoreService.write(KeybindingsSynchroniser.EXTERNAL_USER_DATA_KEYBINDINGS_KEY, content, ref, this.source);
}
private getKeybindingsContentFromSyncContent(syncContent: string): string | null {
......
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IFileService, FileSystemProviderErrorCode, FileSystemProviderError, IFileContent, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files';
import { IUserData, UserDataSyncStoreError, UserDataSyncStoreErrorCode, SyncStatus, IUserDataSyncStoreService, DEFAULT_IGNORED_SETTINGS, IUserDataSyncLogService, IUserDataSyncUtilService, IConflictSetting, ISettingsSyncService, CONFIGURATION_SYNC_STORE_KEY, SyncSource } from 'vs/platform/userDataSync/common/userDataSync';
import { IUserData, UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, DEFAULT_IGNORED_SETTINGS, IUserDataSyncLogService, IUserDataSyncUtilService, IConflictSetting, ISettingsSyncService, CONFIGURATION_SYNC_STORE_KEY, SyncSource } from 'vs/platform/userDataSync/common/userDataSync';
import { VSBuffer } from 'vs/base/common/buffer';
import { parse, ParseError } from 'vs/base/common/json';
import { localize } from 'vs/nls';
......@@ -302,7 +302,7 @@ export class SettingsSynchroniser extends AbstractSynchroniser implements ISetti
} catch (e) {
this.syncPreviewResultPromise = null;
this.setStatus(SyncStatus.Idle);
if (e instanceof UserDataSyncStoreError && e.code === UserDataSyncStoreErrorCode.Rejected) {
if (e instanceof UserDataSyncError && e.code === UserDataSyncErrorCode.Rejected) {
// Rejected as there is a new remote version. Syncing again,
this.logService.info('Settings: Failed to synchronise settings as there is a new remote version available. Synchronizing again...');
return this.sync();
......@@ -454,11 +454,11 @@ export class SettingsSynchroniser extends AbstractSynchroniser implements ISetti
}
private getRemoteUserData(lastSyncData?: IUserData | null): Promise<IUserData> {
return this.userDataSyncStoreService.read(SettingsSynchroniser.EXTERNAL_USER_DATA_SETTINGS_KEY, lastSyncData || null);
return this.userDataSyncStoreService.read(SettingsSynchroniser.EXTERNAL_USER_DATA_SETTINGS_KEY, lastSyncData || null, this.source);
}
private async writeToRemote(content: string, ref: string | null): Promise<string> {
return this.userDataSyncStoreService.write(SettingsSynchroniser.EXTERNAL_USER_DATA_SETTINGS_KEY, content, ref);
return this.userDataSyncStoreService.write(SettingsSynchroniser.EXTERNAL_USER_DATA_SETTINGS_KEY, content, ref, this.source);
}
private async writeToLocal(newContent: string, oldContent: IFileContent | null): Promise<void> {
......
......@@ -4,16 +4,20 @@
*--------------------------------------------------------------------------------------------*/
import { timeout } from 'vs/base/common/async';
import { Event } from 'vs/base/common/event';
import { Event, Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IUserDataSyncLogService, IUserDataSyncService, SyncStatus, IUserDataAuthTokenService, IUserDataAutoSyncService, IUserDataSyncUtilService } from 'vs/platform/userDataSync/common/userDataSync';
import { IUserDataSyncLogService, IUserDataSyncService, SyncStatus, IUserDataAuthTokenService, IUserDataAutoSyncService, IUserDataSyncUtilService, UserDataSyncError, UserDataSyncErrorCode, SyncSource } from 'vs/platform/userDataSync/common/userDataSync';
export class UserDataAutoSync extends Disposable implements IUserDataAutoSyncService {
_serviceBrand: any;
private enabled: boolean = false;
private successiveFailures: number = 0;
private readonly _onError: Emitter<{ code: UserDataSyncErrorCode, source?: SyncSource }> = this._register(new Emitter<{ code: UserDataSyncErrorCode, source?: SyncSource }>());
readonly onError: Event<{ code: UserDataSyncErrorCode, source?: SyncSource }> = this._onError.event;
constructor(
@IConfigurationService private readonly configurationService: IConfigurationService,
......@@ -41,6 +45,7 @@ export class UserDataAutoSync extends Disposable implements IUserDataAutoSyncSer
this.sync(true, auto);
return;
} else {
this.successiveFailures = 0;
if (stopIfDisabled) {
this.userDataSyncService.stop();
this.logService.info('Auto sync stopped.');
......@@ -65,11 +70,17 @@ export class UserDataAutoSync extends Disposable implements IUserDataAutoSyncSer
}
}
await this.userDataSyncService.sync();
this.successiveFailures = 0;
} catch (e) {
this.successiveFailures++;
this.logService.error(e);
this._onError.fire(e instanceof UserDataSyncError ? { code: e.code, source: e.source } : { code: UserDataSyncErrorCode.Unknown });
}
if (this.successiveFailures > 5) {
this._onError.fire({ code: UserDataSyncErrorCode.TooManyFailures });
}
if (loop) {
await timeout(1000 * 60 * 5); // Loop sync for every 5 min.
await timeout(1000 * 60 * 5 * (this.successiveFailures + 1)); // Loop sync for every (successive failures count + 1) times 5 mins interval.
this.sync(loop, true);
}
}
......
......@@ -123,15 +123,18 @@ export interface IUserData {
content: string | null;
}
export enum UserDataSyncStoreErrorCode {
export enum UserDataSyncErrorCode {
TooLarge = 'TooLarge',
Unauthroized = 'Unauthroized',
Rejected = 'Rejected',
Unknown = 'Unknown'
Unknown = 'Unknown',
TooManyFailures = 'TooManyFailures',
ConnectionRefused = 'ConnectionRefused'
}
export class UserDataSyncStoreError extends Error {
export class UserDataSyncError extends Error {
constructor(message: string, public readonly code: UserDataSyncStoreErrorCode) {
constructor(message: string, public readonly code: UserDataSyncErrorCode, public readonly source?: SyncSource) {
super(message);
}
......@@ -151,8 +154,8 @@ export const IUserDataSyncStoreService = createDecorator<IUserDataSyncStoreServi
export interface IUserDataSyncStoreService {
_serviceBrand: undefined;
readonly userDataSyncStore: IUserDataSyncStore | undefined;
read(key: string, oldValue: IUserData | null): Promise<IUserData>;
write(key: string, content: string, ref: string | null): Promise<string>;
read(key: string, oldValue: IUserData | null, source?: SyncSource): Promise<IUserData>;
write(key: string, content: string, ref: string | null, source?: SyncSource): Promise<string>;
clear(): Promise<void>;
}
......@@ -217,6 +220,7 @@ export interface IUserDataSyncService extends ISynchroniser {
export const IUserDataAutoSyncService = createDecorator<IUserDataAutoSyncService>('IUserDataAutoSyncService');
export interface IUserDataAutoSyncService {
_serviceBrand: any;
onError: Event<{ code: UserDataSyncErrorCode, source?: SyncSource }>;
triggerAutoSync(): Promise<void>;
}
......
......@@ -84,6 +84,9 @@ export class UserDataAutoSyncChannel implements IServerChannel {
constructor(private readonly service: IUserDataAutoSyncService) { }
listen(_: unknown, event: string): Event<any> {
switch (event) {
case 'onError': return this.service.onError;
}
throw new Error(`Event not found: ${event}`);
}
......
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { Disposable, } from 'vs/base/common/lifecycle';
import { IUserData, IUserDataSyncStoreService, UserDataSyncStoreErrorCode, UserDataSyncStoreError, IUserDataSyncStore, getUserDataSyncStore, IUserDataAuthTokenService } from 'vs/platform/userDataSync/common/userDataSync';
import { IUserData, IUserDataSyncStoreService, UserDataSyncErrorCode, UserDataSyncError, IUserDataSyncStore, getUserDataSyncStore, IUserDataAuthTokenService, SyncSource } from 'vs/platform/userDataSync/common/userDataSync';
import { IRequestService, asText, isSuccess } from 'vs/platform/request/common/request';
import { URI } from 'vs/base/common/uri';
import { joinPath } from 'vs/base/common/resources';
......@@ -27,7 +27,7 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
this.userDataSyncStore = getUserDataSyncStore(configurationService);
}
async read(key: string, oldValue: IUserData | null): Promise<IUserData> {
async read(key: string, oldValue: IUserData | null, source?: SyncSource): Promise<IUserData> {
if (!this.userDataSyncStore) {
throw new Error('No settings sync store url configured.');
}
......@@ -40,7 +40,7 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
headers['If-None-Match'] = oldValue.ref;
}
const context = await this.request({ type: 'GET', url, headers }, CancellationToken.None);
const context = await this.request({ type: 'GET', url, headers }, source, CancellationToken.None);
if (context.res.statusCode === 304) {
// There is no new value. Hence return the old value.
......@@ -59,7 +59,7 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
return { ref, content };
}
async write(key: string, data: string, ref: string | null): Promise<string> {
async write(key: string, data: string, ref: string | null, source?: SyncSource): Promise<string> {
if (!this.userDataSyncStore) {
throw new Error('No settings sync store url configured.');
}
......@@ -70,12 +70,7 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
headers['If-Match'] = ref;
}
const context = await this.request({ type: 'POST', url, data, headers }, CancellationToken.None);
if (context.res.statusCode === 412) {
// There is a new value. Throw Rejected Error
throw new UserDataSyncStoreError('New data exists', UserDataSyncStoreErrorCode.Rejected);
}
const context = await this.request({ type: 'POST', url, data, headers }, source, CancellationToken.None);
if (!isSuccess(context)) {
throw new Error('Server returned ' + context.res.statusCode);
......@@ -96,14 +91,14 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
const url = joinPath(URI.parse(this.userDataSyncStore.url), 'resource').toString();
const headers: IHeaders = { 'Content-Type': 'text/plain' };
const context = await this.request({ type: 'DELETE', url, headers }, CancellationToken.None);
const context = await this.request({ type: 'DELETE', url, headers }, undefined, CancellationToken.None);
if (!isSuccess(context)) {
throw new Error('Server returned ' + context.res.statusCode);
}
}
private async request(options: IRequestOptions, token: CancellationToken): Promise<IRequestContext> {
private async request(options: IRequestOptions, source: SyncSource | undefined, token: CancellationToken): Promise<IRequestContext> {
const authToken = await this.authTokenService.getToken();
if (!authToken) {
throw new Error('No Auth Token Available.');
......@@ -111,15 +106,30 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
options.headers = options.headers || {};
options.headers['authorization'] = `Bearer ${authToken}`;
const context = await this.requestService.request(options, token);
let context;
try {
context = await this.requestService.request(options, token);
} catch (e) {
throw new UserDataSyncError(`Connection refused for the request '${options.url?.toString()}'.`, UserDataSyncErrorCode.ConnectionRefused, source);
}
if (context.res.statusCode === 401) {
// Throw Unauthorized Error
throw new UserDataSyncStoreError('Unauthorized', UserDataSyncStoreErrorCode.Unauthroized);
throw new UserDataSyncError(`Request '${options.url?.toString()}' is not authorized.`, UserDataSyncErrorCode.Unauthroized, source);
}
return context;
if (context.res.statusCode === 412) {
// There is a new value. Throw Rejected Error
throw new UserDataSyncError(`${options.type} request '${options.url?.toString()}' failed with precondition. There is new data exists for this resource. Make the request again with latest data.`, UserDataSyncErrorCode.Rejected, source);
}
if (context.res.statusCode === 413) {
// Throw Too Large Payload Error
throw new UserDataSyncError(`${options.type} request '${options.url?.toString()}' failed because data is too large.`, UserDataSyncErrorCode.TooLarge, source);
}
return context;
}
}
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IUserDataSyncService, SyncStatus, SyncSource, CONTEXT_SYNC_STATE, IUserDataSyncStore, registerConfiguration, getUserDataSyncStore, ISyncConfiguration, IUserDataAuthTokenService, IUserDataAutoSyncService, USER_DATA_SYNC_SCHEME, toRemoteContentResource, getSyncSourceFromRemoteContentResource } from 'vs/platform/userDataSync/common/userDataSync';
import { IUserDataSyncService, SyncStatus, SyncSource, CONTEXT_SYNC_STATE, IUserDataSyncStore, registerConfiguration, getUserDataSyncStore, ISyncConfiguration, IUserDataAuthTokenService, IUserDataAutoSyncService, USER_DATA_SYNC_SCHEME, toRemoteContentResource, getSyncSourceFromRemoteContentResource, UserDataSyncErrorCode } from 'vs/platform/userDataSync/common/userDataSync';
import { localize } from 'vs/nls';
import { Disposable, MutableDisposable, toDisposable, DisposableStore, dispose } from 'vs/base/common/lifecycle';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
......@@ -44,6 +44,8 @@ import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
import { areSame } from 'vs/platform/userDataSync/common/settingsMerge';
import { getIgnoredSettings } from 'vs/platform/userDataSync/common/settingsSync';
import type { IEditorInput } from 'vs/workbench/common/editor';
import { Action } from 'vs/base/common/actions';
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
const enum AuthStatus {
Initializing = 'Initializing',
......@@ -91,6 +93,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
@IUserDataAuthTokenService private readonly userDataAuthTokenService: IUserDataAuthTokenService,
@IUserDataAutoSyncService userDataAutoSyncService: IUserDataAutoSyncService,
@ITextModelService private readonly textModelResolverService: ITextModelService,
@IPreferencesService private readonly preferencesService: IPreferencesService,
) {
super();
this.userDataSyncStore = getUserDataSyncStore(configurationService);
......@@ -104,6 +107,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
this._register(this.authenticationService.onDidRegisterAuthenticationProvider(e => this.onDidRegisterAuthenticationProvider(e)));
this._register(this.authenticationService.onDidUnregisterAuthenticationProvider(e => this.onDidUnregisterAuthenticationProvider(e)));
this._register(this.authenticationService.onDidChangeSessions(e => this.onDidChangeSessions(e)));
this._register(userDataAutoSyncService.onError(({ code, source }) => this.onAutoSyncError(code, source)));
this.registerActions();
this.initializeActiveAccount().then(_ => {
if (isWeb) {
......@@ -246,6 +250,35 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}
}
private onAutoSyncError(code: UserDataSyncErrorCode, source?: SyncSource): void {
switch (code) {
case UserDataSyncErrorCode.TooManyFailures:
this.disableSync();
this.notificationService.notify({
severity: Severity.Error,
message: localize('too many errors', "Turned off sync because of too many failure attempts. Please open Sync log to check the failures and turn on sync."),
actions: {
primary: [new Action('open sync log', localize('open log', "Show logs"), undefined, true, () => this.showSyncLog())]
}
});
return;
case UserDataSyncErrorCode.TooLarge:
if (source === SyncSource.Keybindings || source === SyncSource.Settings) {
const sourceArea = getSyncAreaLabel(source);
this.disableSync();
this.notificationService.notify({
severity: Severity.Error,
message: localize('too large', "Turned off sync because size of the {0} file to sync is larger than {1}. Please open the file and reduce the size and turn on sync", sourceArea, '1MB'),
actions: {
primary: [new Action('open sync log', localize('open file', "Show {0} file", sourceArea), undefined, true,
() => source === SyncSource.Settings ? this.preferencesService.openGlobalSettings(true) : this.preferencesService.openGlobalKeybindingSettings(true))]
}
});
}
return;
}
}
private async updateBadge(): Promise<void> {
this.badgeDisposable.clear();
......@@ -406,13 +439,17 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}
});
if (result.confirmed) {
await this.configurationService.updateValue(UserDataSyncWorkbenchContribution.ENABLEMENT_SETTING, undefined, ConfigurationTarget.USER);
await this.disableSync();
if (result.checkboxChecked) {
await this.userDataSyncService.reset();
}
}
}
private disableSync(): Promise<void> {
return this.configurationService.updateValue(UserDataSyncWorkbenchContribution.ENABLEMENT_SETTING, undefined, ConfigurationTarget.USER);
}
private async signIn(): Promise<void> {
try {
this.activeAccount = await this.authenticationService.login(this.userDataSyncStore!.authenticationProviderId, ['https://management.core.windows.net/.default', 'offline_access']);
......
......@@ -3,17 +3,19 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IUserDataAutoSyncService } from 'vs/platform/userDataSync/common/userDataSync';
import { IUserDataAutoSyncService, UserDataSyncErrorCode, SyncSource } from 'vs/platform/userDataSync/common/userDataSync';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
import { Disposable } from 'vs/base/common/lifecycle';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { Event } from 'vs/base/common/event';
export class UserDataAutoSyncService extends Disposable implements IUserDataAutoSyncService {
_serviceBrand: undefined;
private readonly channel: IChannel;
get onError(): Event<{ code: UserDataSyncErrorCode, source?: SyncSource }> { return this.channel.listen('onError'); }
constructor(
@ISharedProcessService sharedProcessService: ISharedProcessService
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册