From 8a7928e2707c73066bd3ffca33b323e9bed45e65 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 2 Dec 2019 15:48:58 +0100 Subject: [PATCH] Fix #85210 --- .../sharedProcess/sharedProcessMain.ts | 3 +- .../userDataSync/common/userDataAutoSync.ts | 69 +++++++++++++++++++ .../common/userDataSyncService.ts | 66 +----------------- .../electron-browser/userDataAutoSync.ts | 32 +++++++++ .../userDataSync/browser/userDataAutoSync.ts | 35 ++++++++++ .../userDataSync/browser/userDataSync.ts | 13 +++- .../browser/userDataSyncTrigger.ts | 61 ++++++++++++++++ 7 files changed, 212 insertions(+), 67 deletions(-) create mode 100644 src/vs/platform/userDataSync/common/userDataAutoSync.ts create mode 100644 src/vs/platform/userDataSync/electron-browser/userDataAutoSync.ts create mode 100644 src/vs/workbench/contrib/userDataSync/browser/userDataAutoSync.ts create mode 100644 src/vs/workbench/contrib/userDataSync/browser/userDataSyncTrigger.ts diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index 27469c14739..96ce984b782 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -51,7 +51,7 @@ import { DiskFileSystemProvider } from 'vs/platform/files/electron-browser/diskF import { Schemas } from 'vs/base/common/network'; import { IProductService } from 'vs/platform/product/common/productService'; import { IUserDataSyncService, IUserDataSyncStoreService, ISettingsMergeService, registerConfiguration, IUserDataSyncLogService, IUserDataSyncUtilService } from 'vs/platform/userDataSync/common/userDataSync'; -import { UserDataSyncService, UserDataAutoSync } from 'vs/platform/userDataSync/common/userDataSyncService'; +import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService'; import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService'; import { UserDataSyncChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc'; import { SettingsMergeChannelClient } from 'vs/platform/userDataSync/common/settingsSyncIpc'; @@ -64,6 +64,7 @@ import { AuthTokenChannel } from 'vs/platform/auth/common/authTokenIpc'; import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; import { KeytarCredentialsService } from 'vs/platform/credentials/node/credentialsService'; import { UserDataSyncUtilServiceClient } from 'vs/platform/userDataSync/common/keybindingsSyncIpc'; +import { UserDataAutoSync } from 'vs/platform/userDataSync/electron-browser/userDataAutoSync'; export interface ISharedProcessConfiguration { readonly machineId: string; diff --git a/src/vs/platform/userDataSync/common/userDataAutoSync.ts b/src/vs/platform/userDataSync/common/userDataAutoSync.ts new file mode 100644 index 00000000000..75123459141 --- /dev/null +++ b/src/vs/platform/userDataSync/common/userDataAutoSync.ts @@ -0,0 +1,69 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IUserDataSyncService, SyncStatus, IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { Event } from 'vs/base/common/event'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { timeout } from 'vs/base/common/async'; +import { IAuthTokenService, AuthTokenStatus } from 'vs/platform/auth/common/auth'; + +export class UserDataAutoSync extends Disposable { + + private enabled: boolean = false; + + constructor( + @IConfigurationService private readonly configurationService: IConfigurationService, + @IUserDataSyncService private readonly userDataSyncService: IUserDataSyncService, + @IUserDataSyncLogService private readonly logService: IUserDataSyncLogService, + @IAuthTokenService private readonly authTokenService: IAuthTokenService, + ) { + super(); + this.updateEnablement(false); + this._register(Event.any(authTokenService.onDidChangeStatus, userDataSyncService.onDidChangeStatus)(() => this.updateEnablement(true))); + this._register(Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('sync.enable'))(() => this.updateEnablement(true))); + } + + private updateEnablement(stopIfDisabled: boolean): void { + const enabled = this.isSyncEnabled(); + if (this.enabled === enabled) { + return; + } + + this.enabled = enabled; + if (this.enabled) { + this.logService.info('Syncing configuration started'); + this.sync(true); + return; + } else { + if (stopIfDisabled) { + this.userDataSyncService.stop(); + this.logService.info('Syncing configuration stopped.'); + } + } + + } + + protected async sync(loop: boolean): Promise { + if (this.enabled) { + try { + await this.userDataSyncService.sync(); + } catch (e) { + this.logService.error(e); + } + if (loop) { + await timeout(1000 * 60 * 5); // Loop sync for every 5 min. + this.sync(loop); + } + } + } + + private isSyncEnabled(): boolean { + return this.configurationService.getValue('sync.enable') + && this.userDataSyncService.status !== SyncStatus.Uninitialized + && this.authTokenService.status === AuthTokenStatus.SignedIn; + } + +} diff --git a/src/vs/platform/userDataSync/common/userDataSyncService.ts b/src/vs/platform/userDataSync/common/userDataSyncService.ts index d4a1b83deda..db118026b58 100644 --- a/src/vs/platform/userDataSync/common/userDataSyncService.ts +++ b/src/vs/platform/userDataSync/common/userDataSyncService.ts @@ -3,13 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IUserDataSyncService, SyncStatus, ISynchroniser, IUserDataSyncStoreService, SyncSource, IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync'; +import { IUserDataSyncService, SyncStatus, ISynchroniser, IUserDataSyncStoreService, SyncSource } from 'vs/platform/userDataSync/common/userDataSync'; import { Disposable } from 'vs/base/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { SettingsSynchroniser } from 'vs/platform/userDataSync/common/settingsSync'; import { Emitter, Event } from 'vs/base/common/event'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { timeout } from 'vs/base/common/async'; import { ExtensionsSynchroniser } from 'vs/platform/userDataSync/common/extensionsSync'; import { IExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { IAuthTokenService, AuthTokenStatus } from 'vs/platform/auth/common/auth'; @@ -128,65 +126,3 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ } } - -export class UserDataAutoSync extends Disposable { - - private enabled: boolean = false; - - constructor( - @IConfigurationService private readonly configurationService: IConfigurationService, - @IUserDataSyncService private readonly userDataSyncService: IUserDataSyncService, - @IUserDataSyncStoreService userDataSyncStoreService: IUserDataSyncStoreService, - @IUserDataSyncLogService private readonly logService: IUserDataSyncLogService, - @IAuthTokenService private readonly authTokenService: IAuthTokenService, - ) { - super(); - this.updateEnablement(false); - this._register(Event.any(authTokenService.onDidChangeStatus, userDataSyncService.onDidChangeStatus)(() => this.updateEnablement(true))); - this._register(Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('sync.enable'))(() => this.updateEnablement(true))); - - // Sync immediately if there is a local change. - this._register(Event.debounce(this.userDataSyncService.onDidChangeLocal, () => undefined, 500)(() => this.sync(false))); - } - - private updateEnablement(stopIfDisabled: boolean): void { - const enabled = this.isSyncEnabled(); - if (this.enabled === enabled) { - return; - } - - this.enabled = enabled; - if (this.enabled) { - this.logService.info('Syncing configuration started'); - this.sync(true); - return; - } else { - if (stopIfDisabled) { - this.userDataSyncService.stop(); - this.logService.info('Syncing configuration stopped.'); - } - } - - } - - private async sync(loop: boolean): Promise { - if (this.enabled) { - try { - await this.userDataSyncService.sync(); - } catch (e) { - this.logService.error(e); - } - if (loop) { - await timeout(1000 * 30); // Loop sync for every 30s. - this.sync(loop); - } - } - } - - private isSyncEnabled(): boolean { - return this.configurationService.getValue('sync.enable') - && this.userDataSyncService.status !== SyncStatus.Uninitialized - && this.authTokenService.status === AuthTokenStatus.SignedIn; - } - -} diff --git a/src/vs/platform/userDataSync/electron-browser/userDataAutoSync.ts b/src/vs/platform/userDataSync/electron-browser/userDataAutoSync.ts new file mode 100644 index 00000000000..90ec9533ecd --- /dev/null +++ b/src/vs/platform/userDataSync/electron-browser/userDataAutoSync.ts @@ -0,0 +1,32 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IUserDataSyncService, IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync'; +import { Event } from 'vs/base/common/event'; +import { IElectronService } from 'vs/platform/electron/node/electron'; +import { UserDataAutoSync as BaseUserDataAutoSync } from 'vs/platform/userDataSync/common/userDataAutoSync'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IAuthTokenService } from 'vs/platform/auth/common/auth'; + +export class UserDataAutoSync extends BaseUserDataAutoSync { + + constructor( + @IUserDataSyncService userDataSyncService: IUserDataSyncService, + @IElectronService electronService: IElectronService, + @IConfigurationService configurationService: IConfigurationService, + @IUserDataSyncLogService logService: IUserDataSyncLogService, + @IAuthTokenService authTokenService: IAuthTokenService, + ) { + super(configurationService, userDataSyncService, logService, authTokenService); + + // Sync immediately if there is a local change. + this._register(Event.debounce(Event.any( + electronService.onWindowFocus, + electronService.onWindowOpen, + userDataSyncService.onDidChangeLocal + ), () => undefined, 500)(() => this.sync(false))); + } + +} diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataAutoSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataAutoSync.ts new file mode 100644 index 00000000000..d0d54c3c403 --- /dev/null +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataAutoSync.ts @@ -0,0 +1,35 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IUserDataSyncService, IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IAuthTokenService } from 'vs/platform/auth/common/auth'; +import { Event } from 'vs/base/common/event'; +import { UserDataAutoSync as BaseUserDataAutoSync } from 'vs/platform/userDataSync/common/userDataAutoSync'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { UserDataSyncTrigger } from 'vs/workbench/contrib/userDataSync/browser/userDataSyncTrigger'; +import { IHostService } from 'vs/workbench/services/host/browser/host'; + +export class UserDataAutoSync extends BaseUserDataAutoSync { + + constructor( + @IUserDataSyncService userDataSyncService: IUserDataSyncService, + @IConfigurationService configurationService: IConfigurationService, + @IUserDataSyncLogService logService: IUserDataSyncLogService, + @IAuthTokenService authTokenService: IAuthTokenService, + @IInstantiationService instantiationService: IInstantiationService, + @IHostService hostService: IHostService, + ) { + super(configurationService, userDataSyncService, logService, authTokenService); + + // Sync immediately if there is a local change. + this._register(Event.debounce(Event.any( + userDataSyncService.onDidChangeLocal, + instantiationService.createInstance(UserDataSyncTrigger).onDidTriggerSync, + hostService.onDidChangeFocus + ), () => undefined, 500)(() => this.sync(false))); + } + +} diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts index 1f5577d1189..2a57564f862 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -30,7 +30,8 @@ import { FalseContext } from 'vs/platform/contextkey/common/contextkeys'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { isWeb } from 'vs/base/common/platform'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { UserDataAutoSync } from 'vs/platform/userDataSync/common/userDataSyncService'; +import { UserDataAutoSync } from 'vs/workbench/contrib/userDataSync/browser/userDataAutoSync'; +import { UserDataSyncTrigger } from 'vs/workbench/contrib/userDataSync/browser/userDataSyncTrigger'; const CONTEXT_AUTH_TOKEN_STATE = new RawContextKey('authTokenStatus', AuthTokenStatus.Initializing); const SYNC_PUSH_LIGHT_ICON_URI = URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/userDataSync/browser/media/check-light.svg`)); @@ -78,10 +79,20 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo if (isWeb) { this._register(instantiationService.createInstance(UserDataAutoSync)); + } else { + this._register(instantiationService.createInstance(UserDataSyncTrigger).onDidTriggerSync(() => this.triggerSync())); } } } + private triggerSync(): void { + if (this.configurationService.getValue('sync.enable') + && this.userDataSyncService.status !== SyncStatus.Uninitialized + && this.authTokenService.status === AuthTokenStatus.SignedIn) { + this.userDataSyncService.sync(); + } + } + private onDidChangeAuthTokenStatus(status: AuthTokenStatus) { this.authTokenContext.set(status); if (status === AuthTokenStatus.SignedIn) { diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSyncTrigger.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSyncTrigger.ts new file mode 100644 index 00000000000..21dc9c85367 --- /dev/null +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSyncTrigger.ts @@ -0,0 +1,61 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Event, Emitter } from 'vs/base/common/event'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { SettingsEditor2Input, KeybindingsEditorInput, PreferencesEditorInput } from 'vs/workbench/services/preferences/common/preferencesEditorInput'; +import { isEqual } from 'vs/base/common/resources'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; +import { VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions'; +import { IEditorInput } from 'vs/workbench/common/editor'; +import { IViewlet } from 'vs/workbench/common/viewlet'; + +export class UserDataSyncTrigger extends Disposable { + + private readonly _onDidTriggerSync: Emitter = this._register(new Emitter()); + readonly onDidTriggerSync: Event = this._onDidTriggerSync.event; + + constructor( + @IEditorService editorService: IEditorService, + @IWorkbenchEnvironmentService private readonly workbenchEnvironmentService: IWorkbenchEnvironmentService, + @IViewletService viewletService: IViewletService, + ) { + super(); + this._register(Event.debounce(Event.any( + Event.filter(editorService.onDidActiveEditorChange, () => this.isUserDataEditorInput(editorService.activeEditor)), + Event.filter(viewletService.onDidViewletOpen, viewlet => this.isUserDataViewlet(viewlet)) + ), () => undefined, 500)(() => this._onDidTriggerSync.fire())); + } + + private isUserDataViewlet(viewlet: IViewlet): boolean { + return viewlet.getId() === VIEWLET_ID; + } + + private isUserDataEditorInput(editorInput: IEditorInput | undefined): boolean { + if (!editorInput) { + return false; + } + if (editorInput instanceof SettingsEditor2Input) { + return true; + } + if (editorInput instanceof PreferencesEditorInput) { + return true; + } + if (editorInput instanceof KeybindingsEditorInput) { + return true; + } + const resource = editorInput.getResource(); + if (isEqual(resource, this.workbenchEnvironmentService.settingsResource)) { + return true; + } + if (isEqual(resource, this.workbenchEnvironmentService.keybindingsResource)) { + return true; + } + return false; + } +} +