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

6
import { IServerChannel, IChannel, IPCServer } from 'vs/base/parts/ipc/common/ipc';
7
import { Event } from 'vs/base/common/event';
S
Sandeep Somavarapu 已提交
8
import { IUserDataSyncService, IUserDataSyncUtilService, IUserDataAutoSyncService, IManualSyncTask, IUserDataManifest, IUserDataSyncStoreManagementService, SyncStatus } from 'vs/platform/userDataSync/common/userDataSync';
S
Sandeep Somavarapu 已提交
9 10 11
import { URI } from 'vs/base/common/uri';
import { IStringDictionary } from 'vs/base/common/collections';
import { FormattingOptions } from 'vs/base/common/jsonFormatter';
12
import { IStorageKeysSyncRegistryService, IStorageKey, IExtensionIdWithVersion, AbstractStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
S
Sandeep Somavarapu 已提交
13
import { ILogService } from 'vs/platform/log/common/log';
S
Sandeep Somavarapu 已提交
14
import { IUserDataSyncMachinesService } from 'vs/platform/userDataSync/common/userDataSyncMachines';
15
import { IUserDataSyncAccountService } from 'vs/platform/userDataSync/common/userDataSyncAccount';
16
import { IExtensionIdentifierWithVersion } from 'vs/platform/extensionManagement/common/extensionManagement';
17 18 19

export class UserDataSyncChannel implements IServerChannel {

20
	constructor(private server: IPCServer, private readonly service: IUserDataSyncService, private readonly logService: ILogService) { }
21 22 23 24

	listen(_: unknown, event: string): Event<any> {
		switch (event) {
			case 'onDidChangeStatus': return this.service.onDidChangeStatus;
25
			case 'onDidChangeConflicts': return this.service.onDidChangeConflicts;
26
			case 'onDidChangeLocal': return this.service.onDidChangeLocal;
27
			case 'onDidChangeLastSyncTime': return this.service.onDidChangeLastSyncTime;
S
Sandeep Somavarapu 已提交
28
			case 'onSyncErrors': return this.service.onSyncErrors;
S
Sandeep Somavarapu 已提交
29 30
			case 'onDidResetLocal': return this.service.onDidResetLocal;
			case 'onDidResetRemote': return this.service.onDidResetRemote;
31 32 33 34
		}
		throw new Error(`Event not found: ${event}`);
	}

S
Sandeep Somavarapu 已提交
35 36 37 38 39 40
	async call(context: any, command: string, args?: any): Promise<any> {
		try {
			const result = await this._call(context, command, args);
			return result;
		} catch (e) {
			this.logService.error(e);
41
			throw e;
S
Sandeep Somavarapu 已提交
42 43 44 45
		}
	}

	private _call(context: any, command: string, args?: any): Promise<any> {
46
		switch (command) {
47
			case '_getInitialData': return Promise.resolve([this.service.status, this.service.conflicts, this.service.lastSyncTime]);
48 49 50

			case 'createManualSyncTask': return this.createManualSyncTask();

51
			case 'replace': return this.service.replace(URI.revive(args[0]));
S
Sandeep Somavarapu 已提交
52
			case 'reset': return this.service.reset();
S
Sandeep Somavarapu 已提交
53
			case 'resetRemote': return this.service.resetRemote();
S
Sandeep Somavarapu 已提交
54
			case 'resetLocal': return this.service.resetLocal();
55
			case 'hasPreviouslySynced': return this.service.hasPreviouslySynced();
56
			case 'hasLocalData': return this.service.hasLocalData();
57
			case 'accept': return this.service.accept(args[0], URI.revive(args[1]), args[2], args[3]);
58 59 60 61
			case 'resolveContent': return this.service.resolveContent(URI.revive(args[0]));
			case 'getLocalSyncResourceHandles': return this.service.getLocalSyncResourceHandles(args[0]);
			case 'getRemoteSyncResourceHandles': return this.service.getRemoteSyncResourceHandles(args[0]);
			case 'getAssociatedResources': return this.service.getAssociatedResources(args[0], { created: args[1].created, uri: URI.revive(args[1].uri) });
62
			case 'getMachineId': return this.service.getMachineId(args[0], { created: args[1].created, uri: URI.revive(args[1].uri) });
63 64 65
		}
		throw new Error('Invalid call');
	}
66

S
Sandeep Somavarapu 已提交
67
	private async createManualSyncTask(): Promise<{ id: string, manifest: IUserDataManifest | null, status: SyncStatus }> {
68
		const manualSyncTask = await this.service.createManualSyncTask();
S
Sandeep Somavarapu 已提交
69
		const manualSyncTaskChannel = new ManualSyncTaskChannel(manualSyncTask, this.logService);
70
		this.server.registerChannel(`manualSyncTask-${manualSyncTask.id}`, manualSyncTaskChannel);
S
Sandeep Somavarapu 已提交
71
		return { id: manualSyncTask.id, manifest: manualSyncTask.manifest, status: manualSyncTask.status };
72 73 74 75 76
	}
}

class ManualSyncTaskChannel implements IServerChannel {

S
Sandeep Somavarapu 已提交
77 78 79 80
	constructor(
		private readonly manualSyncTask: IManualSyncTask,
		private readonly logService: ILogService
	) { }
81 82

	listen(_: unknown, event: string): Event<any> {
83 84 85
		switch (event) {
			case 'onSynchronizeResources': return this.manualSyncTask.onSynchronizeResources;
		}
86 87 88 89
		throw new Error(`Event not found: ${event}`);
	}

	async call(context: any, command: string, args?: any): Promise<any> {
S
Sandeep Somavarapu 已提交
90 91 92 93 94 95 96 97 98 99
		try {
			const result = await this._call(context, command, args);
			return result;
		} catch (e) {
			this.logService.error(e);
			throw e;
		}
	}

	private async _call(context: any, command: string, args?: any): Promise<any> {
100 101 102
		switch (command) {
			case 'preview': return this.manualSyncTask.preview();
			case 'accept': return this.manualSyncTask.accept(URI.revive(args[0]), args[1]);
103
			case 'merge': return this.manualSyncTask.merge(URI.revive(args[0]));
S
Sandeep Somavarapu 已提交
104
			case 'discard': return this.manualSyncTask.discard(URI.revive(args[0]));
S
Sandeep Somavarapu 已提交
105
			case 'discardConflicts': return this.manualSyncTask.discardConflicts();
106
			case 'apply': return this.manualSyncTask.apply();
107 108 109
			case 'pull': return this.manualSyncTask.pull();
			case 'push': return this.manualSyncTask.push();
			case 'stop': return this.manualSyncTask.stop();
S
Sandeep Somavarapu 已提交
110
			case '_getStatus': return this.manualSyncTask.status;
111
			case 'dispose': return this.manualSyncTask.dispose();
112 113 114 115
		}
		throw new Error('Invalid call');
	}

116
}
S
Sandeep Somavarapu 已提交
117

S
Sandeep Somavarapu 已提交
118 119 120 121 122
export class UserDataAutoSyncChannel implements IServerChannel {

	constructor(private readonly service: IUserDataAutoSyncService) { }

	listen(_: unknown, event: string): Event<any> {
S
Sandeep Somavarapu 已提交
123 124 125
		switch (event) {
			case 'onError': return this.service.onError;
		}
S
Sandeep Somavarapu 已提交
126 127 128 129 130
		throw new Error(`Event not found: ${event}`);
	}

	call(context: any, command: string, args?: any): Promise<any> {
		switch (command) {
S
Sandeep Somavarapu 已提交
131
			case 'triggerSync': return this.service.triggerSync(args[0], args[1], args[2]);
132
			case 'turnOn': return this.service.turnOn();
S
Sandeep Somavarapu 已提交
133
			case 'turnOff': return this.service.turnOff(args[0]);
S
Sandeep Somavarapu 已提交
134 135 136 137 138
		}
		throw new Error('Invalid call');
	}
}

S
Sandeep Somavarapu 已提交
139 140 141 142 143 144 145 146 147 148
export class UserDataSycnUtilServiceChannel implements IServerChannel {

	constructor(private readonly service: IUserDataSyncUtilService) { }

	listen(_: unknown, event: string): Event<any> {
		throw new Error(`Event not found: ${event}`);
	}

	call(context: any, command: string, args?: any): Promise<any> {
		switch (command) {
S
Sandeep Somavarapu 已提交
149
			case 'resolveDefaultIgnoredSettings': return this.service.resolveDefaultIgnoredSettings();
S
Sandeep Somavarapu 已提交
150 151 152 153 154 155 156 157 158
			case 'resolveUserKeybindings': return this.service.resolveUserBindings(args[0]);
			case 'resolveFormattingOptions': return this.service.resolveFormattingOptions(URI.revive(args[0]));
		}
		throw new Error('Invalid call');
	}
}

export class UserDataSyncUtilServiceClient implements IUserDataSyncUtilService {

159
	declare readonly _serviceBrand: undefined;
S
Sandeep Somavarapu 已提交
160 161 162 163

	constructor(private readonly channel: IChannel) {
	}

S
Sandeep Somavarapu 已提交
164 165 166 167
	async resolveDefaultIgnoredSettings(): Promise<string[]> {
		return this.channel.call('resolveDefaultIgnoredSettings');
	}

S
Sandeep Somavarapu 已提交
168 169 170 171 172 173 174 175 176 177
	async resolveUserBindings(userbindings: string[]): Promise<IStringDictionary<string>> {
		return this.channel.call('resolveUserKeybindings', [userbindings]);
	}

	async resolveFormattingOptions(file: URI): Promise<FormattingOptions> {
		return this.channel.call('resolveFormattingOptions', [file]);
	}

}

178 179
type StorageKeysSyncRegistryServiceInitData = { storageKeys: ReadonlyArray<IStorageKey>, extensionsStorageKeys: ReadonlyArray<[IExtensionIdWithVersion, ReadonlyArray<string>]> };

180 181 182 183 184 185 186
export class StorageKeysSyncRegistryChannel implements IServerChannel {

	constructor(private readonly service: IStorageKeysSyncRegistryService) { }

	listen(_: unknown, event: string): Event<any> {
		switch (event) {
			case 'onDidChangeStorageKeys': return this.service.onDidChangeStorageKeys;
187
			case 'onDidChangeExtensionStorageKeys': return this.service.onDidChangeExtensionStorageKeys;
188 189 190 191 192 193
		}
		throw new Error(`Event not found: ${event}`);
	}

	call(context: any, command: string, args?: any): Promise<any> {
		switch (command) {
194
			case '_getInitialData': return Promise.resolve<StorageKeysSyncRegistryServiceInitData>({ storageKeys: this.service.storageKeys, extensionsStorageKeys: this.service.extensionsStorageKeys });
195
			case 'registerStorageKey': return Promise.resolve(this.service.registerStorageKey(args[0]));
196
			case 'registerExtensionStorageKeys': return Promise.resolve(this.service.registerExtensionStorageKeys(args[0], args[1]));
197 198 199 200 201
		}
		throw new Error('Invalid call');
	}
}

202
export class StorageKeysSyncRegistryChannelClient extends AbstractStorageKeysSyncRegistryService {
203

204
	declare readonly _serviceBrand: undefined;
205 206 207

	constructor(private readonly channel: IChannel) {
		super();
208
		this.channel.call<StorageKeysSyncRegistryServiceInitData>('_getInitialData').then(({ storageKeys, extensionsStorageKeys }) => {
209
			this.updateStorageKeys(storageKeys);
210
			this.updateExtensionsStorageKeys(extensionsStorageKeys);
211
			this._register(this.channel.listen<ReadonlyArray<IStorageKey>>('onDidChangeStorageKeys')(storageKeys => this.updateStorageKeys(storageKeys)));
212
			this._register(this.channel.listen<[IExtensionIdentifierWithVersion, string[]]>('onDidChangeExtensionStorageKeys')(e => this.updateExtensionStorageKeys(e[0], e[1])));
213 214 215 216
		});
	}

	private async updateStorageKeys(storageKeys: ReadonlyArray<IStorageKey>): Promise<void> {
217 218 219 220
		this._storageKeys.clear();
		for (const storageKey of storageKeys) {
			this._storageKeys.set(storageKey.key, storageKey);
		}
221 222 223
		this._onDidChangeStorageKeys.fire(this.storageKeys);
	}

224 225 226 227 228 229
	private async updateExtensionsStorageKeys(extensionStorageKeys: ReadonlyArray<[IExtensionIdentifierWithVersion, ReadonlyArray<string>]>): Promise<void> {
		for (const [extension, keys] of extensionStorageKeys) {
			this.updateExtensionStorageKeys(extension, [...keys]);
		}
	}

230 231 232 233
	registerStorageKey(storageKey: IStorageKey): void {
		this.channel.call('registerStorageKey', [storageKey]);
	}

234 235 236 237
	registerExtensionStorageKeys(extension: IExtensionIdentifierWithVersion, keys: string[]): void {
		this.channel.call('registerExtensionStorageKeys', [extension, keys]);
	}

238
}
S
Sandeep Somavarapu 已提交
239 240 241 242 243 244

export class UserDataSyncMachinesServiceChannel implements IServerChannel {

	constructor(private readonly service: IUserDataSyncMachinesService) { }

	listen(_: unknown, event: string): Event<any> {
S
Sandeep Somavarapu 已提交
245 246 247
		switch (event) {
			case 'onDidChange': return this.service.onDidChange;
		}
S
Sandeep Somavarapu 已提交
248 249 250 251 252 253
		throw new Error(`Event not found: ${event}`);
	}

	async call(context: any, command: string, args?: any): Promise<any> {
		switch (command) {
			case 'getMachines': return this.service.getMachines();
254
			case 'addCurrentMachine': return this.service.addCurrentMachine();
S
Sandeep Somavarapu 已提交
255 256
			case 'removeCurrentMachine': return this.service.removeCurrentMachine();
			case 'renameMachine': return this.service.renameMachine(args[0], args[1]);
257
			case 'setEnablement': return this.service.setEnablement(args[0], args[1]);
S
Sandeep Somavarapu 已提交
258 259 260 261 262
		}
		throw new Error('Invalid call');
	}

}
263 264 265 266 267 268

export class UserDataSyncAccountServiceChannel implements IServerChannel {
	constructor(private readonly service: IUserDataSyncAccountService) { }

	listen(_: unknown, event: string): Event<any> {
		switch (event) {
S
Sandeep Somavarapu 已提交
269
			case 'onDidChangeAccount': return this.service.onDidChangeAccount;
270 271 272 273 274 275 276
			case 'onTokenFailed': return this.service.onTokenFailed;
		}
		throw new Error(`Event not found: ${event}`);
	}

	call(context: any, command: string, args?: any): Promise<any> {
		switch (command) {
S
Sandeep Somavarapu 已提交
277
			case '_getInitialData': return Promise.resolve(this.service.account);
278 279 280 281 282 283
			case 'updateAccount': return this.service.updateAccount(args);
		}
		throw new Error('Invalid call');
	}
}

S
Sandeep Somavarapu 已提交
284 285 286 287
export class UserDataSyncStoreManagementServiceChannel implements IServerChannel {
	constructor(private readonly service: IUserDataSyncStoreManagementService) { }

	listen(_: unknown, event: string): Event<any> {
S
Sandeep Somavarapu 已提交
288 289 290
		switch (event) {
			case 'onDidChangeUserDataSyncStore': return this.service.onDidChangeUserDataSyncStore;
		}
S
Sandeep Somavarapu 已提交
291 292 293 294 295 296 297 298 299 300 301
		throw new Error(`Event not found: ${event}`);
	}

	call(context: any, command: string, args?: any): Promise<any> {
		switch (command) {
			case 'switch': return this.service.switch(args[0]);
			case 'getPreviousUserDataSyncStore': return this.service.getPreviousUserDataSyncStore();
		}
		throw new Error('Invalid call');
	}
}