userDataSyncStoreService.ts ×36

Frontier kind: Code frontier

unlabeled · c_9beccbfbc7ef

249 tests · 24456 LOC · 133 files · introduces 0 tests · 476 LOC · 13 files

Introduces — evidence that enters the hierarchy at this concept

Code
87 ranges476 lines · 13 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
3780 ranges24456 lines · 133 files · Browse complete extent
All tests (intent)
249 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

13 files ranked by introduced lines: 476 introduced LOC across 87 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/platform/userDataSync/common/userDataSyncStoreService.ts 165 introduced LOC · 36 ranges

Open complete file

68
69 constructor(
70 > @IProductService protected readonly productService: IProductService, userDataSyncStoreService.ts
71 > @IConfigurationService protected readonly configurationService: IConfigurationService,
72 > @IStorageService protected readonly storageService: IStorageService,
73 > ) {
74 > super();
75 > this.updateUserDataSyncStore();
76 > const disposable = this._register(new DisposableStore());
77 > this._register(Event.filter(storageService.onDidChangeValue(StorageScope.APPLICATION, SYNC_SERVICE_URL_TYPE, disposable), () => this.userDataSyncStoreType !== this.userDataSyncStore?.type, disposable)(() => this.updateUserDataSyncStore()));
78 > }
79
80 protected updateUserDataSyncStore(): void {
81 > this._userDataSyncStore = this.toUserDataSyncStore(this.productService[CONFIGURATION_SYNC_STORE_KEY]); userDataSyncStoreService.ts
82 > this._onDidChangeUserDataSyncStore.fire();
83 > }
84
85 protected toUserDataSyncStore(configurationSyncStore: ConfigurationSyncStore & { web?: ConfigurationSyncStore } | undefined): UserDataSyncStore | undefined {
86 > if (!configurationSyncStore) { userDataSyncStoreService.ts
87 return undefined;
88 }
89 > // Check for web overrides for backward compatibility while reading previous store userDataSyncStoreService.ts
90 > configurationSyncStore = isWeb && configurationSyncStore.web ? { ...configurationSyncStore, ...configurationSyncStore.web } : configurationSyncStore;
91 > if (isString(configurationSyncStore.url)
92 > && isObject(configurationSyncStore.authenticationProviders)
93 > && Object.keys(configurationSyncStore.authenticationProviders).every(authenticationProviderId => Array.isArray(configurationSyncStore.authenticationProviders[authenticationProviderId].scopes))
94 > ) {
95 > const syncStore = configurationSyncStore as ConfigurationSyncStore;
96 > const canSwitch = !!syncStore.canSwitch;
97 > const defaultType: UserDataSyncStoreType = syncStore.url === syncStore.insidersUrl ? 'insiders' : 'stable';
98 > const type: UserDataSyncStoreType = (canSwitch ? this.userDataSyncStoreType : undefined) || defaultType;
99 > const url = type === 'insiders' ? syncStore.insidersUrl
100 : type === 'stable' ? syncStore.stableUrl
101 : syncStore.url;
103 > url: URI.parse(url),
104 > type,
105 > defaultType,
106 > defaultUrl: URI.parse(syncStore.url),
107 > stableUrl: URI.parse(syncStore.stableUrl),
108 > insidersUrl: URI.parse(syncStore.insidersUrl),
109 > canSwitch,
110 > authenticationProviders: Object.keys(syncStore.authenticationProviders).reduce<IAuthenticationProvider[]>((result, id) => {
111 > result.push({ id, scopes: syncStore.authenticationProviders[id].scopes });
112 > return result;
113 > }, [])
114 > };
115 > }
116 return undefined;
118
119 abstract switch(type: UserDataSyncStoreType): Promise<void>;
127
128 constructor(
129 > @IProductService productService: IProductService, userDataSyncStoreService.ts
130 > @IConfigurationService configurationService: IConfigurationService,
131 > @IStorageService storageService: IStorageService,
132 > ) {
133 > super(productService, configurationService, storageService);
134 >
135 > const previousConfigurationSyncStore = this.storageService.get(SYNC_PREVIOUS_STORE, StorageScope.APPLICATION);
136 > if (previousConfigurationSyncStore) {
137 this.previousConfigurationSyncStore = JSON.parse(previousConfigurationSyncStore);
138 }
140 > const syncStore = this.productService[CONFIGURATION_SYNC_STORE_KEY];
141 > if (syncStore) {
142 > this.storageService.store(SYNC_PREVIOUS_STORE, JSON.stringify(syncStore), StorageScope.APPLICATION, StorageTarget.MACHINE);
143 > } else {
144 this.storageService.remove(SYNC_PREVIOUS_STORE, StorageScope.APPLICATION);
145 }
147
148 async switch(type: UserDataSyncStoreType): Promise<void> {
178
179 constructor(
180 > userDataSyncStoreUrl: URI | undefined, userDataSyncStoreService.ts
181 > @IProductService productService: IProductService,
182 > @IRequestService private readonly requestService: IRequestService,
183 > @IUserDataSyncLogService private readonly logService: IUserDataSyncLogService,
184 > @IEnvironmentService environmentService: IEnvironmentService,
185 > @IFileService fileService: IFileService,
186 > @IStorageService private readonly storageService: IStorageService,
187 > ) {
188 > super();
189 > this.updateUserDataSyncStoreUrl(userDataSyncStoreUrl);
190 > this.commonHeadersPromise = getServiceMachineId(environmentService, fileService, storageService)
191 > .then(uuid => {
192 > const headers: IHeaders = {
193 > 'X-Client-Name': `${productService.applicationName}${isWeb ? '-web' : ''}`,
194 > 'X-Client-Version': productService.version,
195 > };
196 > if (productService.commit) {
197 headers['X-Client-Commit'] = productService.commit;
198 }
199 > return headers; userDataSyncStoreService.ts
200 > });
201 >
202 > /* A requests session that limits requests per sessions */
203 > this.session = new RequestsSession(REQUEST_SESSION_LIMIT, REQUEST_SESSION_INTERVAL, this.requestService, this.logService);
204 > this.initDonotMakeRequestsUntil();
205 > this._register(toDisposable(() => {
206 > if (this.resetDonotMakeRequestsUntilPromise) {
207 this.resetDonotMakeRequestsUntilPromise.cancel();
208 this.resetDonotMakeRequestsUntilPromise = undefined;
209 }
211 > }
212
213 setAuthToken(token: string, type: string): void {
214 > this.authToken = { token, type }; userDataSyncStoreService.ts
215 > }
216
217 protected updateUserDataSyncStoreUrl(userDataSyncStoreUrl: URI | undefined): void {
218 > this.userDataSyncStoreUrl = userDataSyncStoreUrl ? joinPath(userDataSyncStoreUrl, 'v1') : undefined; userDataSyncStoreService.ts
219 > }
220
221 private initDonotMakeRequestsUntil(): void {
222 > const donotMakeRequestsUntil = this.storageService.getNumber(DONOT_MAKE_REQUESTS_UNTIL_KEY, StorageScope.APPLICATION); userDataSyncStoreService.ts
223 > if (donotMakeRequestsUntil && Date.now() < donotMakeRequestsUntil) {
224 this.setDonotMakeRequestsUntil(new Date(donotMakeRequestsUntil));
225 }
227
228 private resetDonotMakeRequestsUntilPromise: CancelablePromise<void> | undefined = undefined;
229 private setDonotMakeRequestsUntil(donotMakeRequestsUntil: Date | undefined): void {
230 > if (this._donotMakeRequestsUntil?.getTime() !== donotMakeRequestsUntil?.getTime()) { userDataSyncStoreService.ts
231 this._donotMakeRequestsUntil = donotMakeRequestsUntil;
232
554
555 private async request(url: string, options: IRequestOptions, successCodes: number[], token: CancellationToken): Promise<IRequestContext> {
556 > if (!this.authToken) { userDataSyncStoreService.ts
557 throw new UserDataSyncStoreError('No Auth Token Available', url, UserDataSyncErrorCode.Unauthorized, undefined, undefined);
558 }
560 > if (this._donotMakeRequestsUntil && Date.now() < this._donotMakeRequestsUntil.getTime()) {
561 throw new UserDataSyncStoreError(`${options.type} request '${url}' failed because of too many requests (429).`, url, UserDataSyncErrorCode.TooManyRequestsAndRetryAfter, undefined, undefined);
562 }
563 > this.setDonotMakeRequestsUntil(undefined); userDataSyncStoreService.ts
564 >
565 > const commonHeaders = await this.commonHeadersPromise;
566 > options.headers = {
567 > ...(options.headers || {}),
568 > ...commonHeaders,
569 > 'X-Account-Type': this.authToken.type,
570 > 'authorization': `Bearer ${this.authToken.token}`,
571 > };
572 >
573 > // Add session headers
574 > this.addSessionHeaders(options.headers);
575 >
576 > this.logService.trace('Sending request to server', { url, type: options.type, headers: { ...options.headers, ...{ authorization: undefined } } });
577 >
578 > let context;
579 > try {
580 > context = await this.session.request(url, options, token);
581 > } catch (e) {
582 if (!(e instanceof UserDataSyncStoreError)) {
583 let code = UserDataSyncErrorCode.RequestFailed;
614 throw e;
615 }
617 > const operationId = context.res.headers[HEADER_OPERATION_ID];
618 > const requestInfo = { url, status: context.res.statusCode, 'execution-id': options.headers[HEADER_EXECUTION_ID], 'operation-id': operationId };
619 > const isSuccess = isSuccessContext(context) || (context.res.statusCode && successCodes.includes(context.res.statusCode));
620 > let failureMessage = '';
621 > if (isSuccess) {
622 > this.logService.trace('Request succeeded', requestInfo);
623 > } else {
624 failureMessage = await asText(context) || '';
625 this.logService.info('Request failed', requestInfo, failureMessage);
626 }
628 > if (context.res.statusCode === 401 || context.res.statusCode === 403) {
629 this.authToken = undefined;
630 if (context.res.statusCode === 401) {
637 }
638 }
640 > this._onTokenSucceed.fire();
641 >
642 > if (context.res.statusCode === 404) {
643 throw new UserDataSyncStoreError(`${options.type} request '${url}' failed because the requested resource is not found (404).`, url, UserDataSyncErrorCode.NotFound, context.res.statusCode, operationId);
644 }
646 > if (context.res.statusCode === 405) {
647 throw new UserDataSyncStoreError(`${options.type} request '${url}' failed because the requested endpoint is not found (405). ${failureMessage}`, url, UserDataSyncErrorCode.MethodNotFound, context.res.statusCode, operationId);
648 }
650 > if (context.res.statusCode === 409) {
651 throw new UserDataSyncStoreError(`${options.type} request '${url}' failed because of Conflict (409). There is new data for this resource. Make the request again with latest data.`, url, UserDataSyncErrorCode.Conflict, context.res.statusCode, operationId);
652 }
654 > if (context.res.statusCode === 410) {
655 throw new UserDataSyncStoreError(`${options.type} request '${url}' failed because the requested resource is not longer available (410).`, url, UserDataSyncErrorCode.Gone, context.res.statusCode, operationId);
656 }
658 > if (context.res.statusCode === 412) {
659 throw new UserDataSyncStoreError(`${options.type} request '${url}' failed because of Precondition Failed (412). There is new data for this resource. Make the request again with latest data.`, url, UserDataSyncErrorCode.PreconditionFailed, context.res.statusCode, operationId);
660 }
662 > if (context.res.statusCode === 413) {
663 throw new UserDataSyncStoreError(`${options.type} request '${url}' failed because of too large payload (413).`, url, UserDataSyncErrorCode.TooLarge, context.res.statusCode, operationId);
664 }
666 > if (context.res.statusCode === 426) {
667 throw new UserDataSyncStoreError(`${options.type} request '${url}' failed with status Upgrade Required (426). Please upgrade the client and try again.`, url, UserDataSyncErrorCode.UpgradeRequired, context.res.statusCode, operationId);
668 }
670 > if (context.res.statusCode === 429) {
671 const retryAfter = context.res.headers['retry-after'];
672 if (retryAfter) {
677 }
678 }
680 > if (!isSuccess) {
681 throw new UserDataSyncStoreError('Server returned ' + context.res.statusCode, url, UserDataSyncErrorCode.Unknown, context.res.statusCode, operationId);
682 }
684 > return context;
685 > }
686
687 private addSessionHeaders(headers: IHeaders): void {
688 > let machineSessionId = this.storageService.get(MACHINE_SESSION_ID_KEY, StorageScope.APPLICATION); userDataSyncStoreService.ts
689 > if (machineSessionId === undefined) {
690 > machineSessionId = generateUuid();
691 > this.storageService.store(MACHINE_SESSION_ID_KEY, machineSessionId, StorageScope.APPLICATION, StorageTarget.MACHINE);
692 > }
693 > headers['X-Machine-Session-Id'] = machineSessionId;
694 >
695 > const userSessionId = this.storageService.get(USER_SESSION_ID_KEY, StorageScope.APPLICATION);
696 > if (userSessionId !== undefined) {
697 headers['X-User-Session-Id'] = userSessionId;
698 }
700
701 }
706
707 constructor(
708 > @IUserDataSyncStoreManagementService userDataSyncStoreManagementService: IUserDataSyncStoreManagementService, userDataSyncStoreService.ts
709 > @IProductService productService: IProductService,
710 > @IRequestService requestService: IRequestService,
711 > @IUserDataSyncLogService logService: IUserDataSyncLogService,
712 > @IEnvironmentService environmentService: IEnvironmentService,
713 > @IFileService fileService: IFileService,
714 > @IStorageService storageService: IStorageService,
715 > ) {
716 > super(userDataSyncStoreManagementService.userDataSyncStore?.url, productService, requestService, logService, environmentService, fileService, storageService);
717 > this._register(userDataSyncStoreManagementService.onDidChangeUserDataSyncStore(() => this.updateUserDataSyncStoreUrl(userDataSyncStoreManagementService.userDataSyncStore?.url)));
718 > }
719
720 }
src/vs/platform/userDataSync/test/common/userDataSyncClient.ts 124 introduced LOC · 19 ranges

Open complete file

53
54 constructor(readonly testServer: UserDataSyncTestServer = new UserDataSyncTestServer()) {
55 > super(); userDataSyncClient.ts
56 > this.instantiationService = this._register(new TestInstantiationService());
57 > }
58
59 async setUp(empty: boolean = false): Promise<void> {
60 > this._register(registerConfiguration()); userDataSyncClient.ts
61 >
62 > const logService = this.instantiationService.stub(ILogService, new NullLogService());
63 >
64 > const userRoamingDataHome = URI.file('userdata').with({ scheme: Schemas.inMemory });
65 > const userDataSyncHome = joinPath(userRoamingDataHome, '.sync');
66 > const environmentService = this.instantiationService.stub(IEnvironmentService, {
67 > userDataSyncHome,
68 > userRoamingDataHome,
69 > cacheHome: joinPath(userRoamingDataHome, 'cache'),
70 > argvResource: joinPath(userRoamingDataHome, 'argv.json'),
71 > sync: 'on'
72 > });
73 >
74 > this.instantiationService.stub(IProductService, {
75 > _serviceBrand: undefined, ...product, ...{
76 > 'configurationSync.store': {
77 > url: this.testServer.url,
78 > stableUrl: this.testServer.url,
79 > insidersUrl: this.testServer.url,
80 > canSwitch: false,
81 > authenticationProviders: { 'test': { scopes: [] } }
82 > }
83 > }
84 > });
85 >
86 > const fileService = this._register(new FileService(logService));
87 > this._register(fileService.registerProvider(Schemas.inMemory, this._register(new InMemoryFileSystemProvider())));
88 > this._register(fileService.registerProvider(USER_DATA_SYNC_SCHEME, this._register(new InMemoryFileSystemProvider())));
89 > this.instantiationService.stub(IFileService, fileService);
90 >
91 > const uriIdentityService = this._register(this.instantiationService.createInstance(UriIdentityService));
92 > this.instantiationService.stub(IUriIdentityService, uriIdentityService);
93 >
94 > const userDataProfilesService = this._register(new InMemoryUserDataProfilesService(environmentService, fileService, uriIdentityService, logService));
95 > this.instantiationService.stub(IUserDataProfilesService, userDataProfilesService);
96 >
97 > const storageService = this._register(new TestStorageService(userDataProfilesService.defaultProfile));
98 > this.instantiationService.stub(IStorageService, this._register(storageService));
99 > this.instantiationService.stub(IUserDataProfileStorageService, this._register(new TestUserDataProfileStorageService(false, storageService)));
100 >
101 > const configurationService = this._register(new ConfigurationService(userDataProfilesService.defaultProfile.settingsResource, fileService, new NullPolicyService(), logService));
102 > await configurationService.initialize();
103 > this.instantiationService.stub(IConfigurationService, configurationService);
104 >
105 > this.instantiationService.stub(IMeteredConnectionService, { isConnectionMetered: false, onDidChangeIsConnectionMetered: new Emitter<boolean>().event });
106 >
107 > this.instantiationService.stub(IRequestService, this.testServer);
108 >
109 > this.instantiationService.stub(IUserDataSyncLogService, logService);
110 > this.instantiationService.stub(ITelemetryService, NullTelemetryService);
111 > this.instantiationService.stub(IUserDataSyncStoreManagementService, this._register(this.instantiationService.createInstance(UserDataSyncStoreManagementService)));
112 > this.instantiationService.stub(IUserDataSyncStoreService, this._register(this.instantiationService.createInstance(UserDataSyncStoreService)));
113 >
114 > const userDataSyncAccountService: IUserDataSyncAccountService = this._register(this.instantiationService.createInstance(UserDataSyncAccountService));
115 > await userDataSyncAccountService.updateAccount({ authenticationProviderId: 'authenticationProviderId', token: 'token' });
116 > this.instantiationService.stub(IUserDataSyncAccountService, userDataSyncAccountService);
117 >
118 > this.instantiationService.stub(IUserDataSyncMachinesService, this._register(this.instantiationService.createInstance(UserDataSyncMachinesService)));
119 > this.instantiationService.stub(IUserDataSyncLocalStoreService, this._register(this.instantiationService.createInstance(UserDataSyncLocalStoreService)));
120 > this.instantiationService.stub(IUserDataSyncUtilService, new TestUserDataSyncUtilService());
121 > this.instantiationService.stub(IUserDataSyncEnablementService, this._register(this.instantiationService.createInstance(UserDataSyncEnablementService)));
122 >
123 > this.instantiationService.stub(IExtensionManagementService, {
124 > async getInstalled() { return []; },
125 > onDidInstallExtensions: new Emitter<readonly InstallExtensionResult[]>().event,
126 > onDidUninstallExtension: new Emitter<DidUninstallExtensionEvent>().event,
127 > });
128 > this.instantiationService.stub(IGlobalExtensionEnablementService, this._register(this.instantiationService.createInstance(GlobalExtensionEnablementService)));
129 > this.instantiationService.stub(IExtensionStorageService, this._register(this.instantiationService.createInstance(ExtensionStorageService)));
130 > this.instantiationService.stub(IIgnoredExtensionsManagementService, this.instantiationService.createInstance(IgnoredExtensionsManagementService));
131 > this.instantiationService.stub(IExtensionGalleryService, {
132 > isEnabled() { return true; },
133 > async getCompatibleExtension() { return null; }
134 > });
135 >
136 > this.instantiationService.stub(IUserDataSyncService, this._register(this.instantiationService.createInstance(UserDataSyncService)));
137 >
138 > if (!empty) {
139 await fileService.writeFile(userDataProfilesService.defaultProfile.settingsResource, VSBuffer.fromString(JSON.stringify({})));
140 await fileService.writeFile(userDataProfilesService.defaultProfile.keybindingsResource, VSBuffer.fromString(JSON.stringify([])));
144 await fileService.writeFile(environmentService.argvResource, VSBuffer.fromString(JSON.stringify({ 'locale': 'en' })));
145 }
146 > await configurationService.reloadConfiguration(); userDataSyncClient.ts
147 >
148 > // `prompts` resource is disabled by default, so enable it for tests
149 > this.instantiationService
150 > .get(IUserDataSyncEnablementService)
151 > .setResourceEnablement(SyncResource.Prompts, true);
152 > }
153
154 async sync(): Promise<void> {
210
211 async request(options: IRequestOptions, token: CancellationToken): Promise<IRequestContext> {
212 > if (this._requests.length === this.rateLimit) { userDataSyncClient.ts
213 return this.toResponse(429, this.retryAfter ? { 'retry-after': `${this.retryAfter}` } : undefined);
214 }
215 > const headers: IHeaders = {}; userDataSyncClient.ts
216 > if (options.headers) {
217 > if (options.headers['If-None-Match']) {
218 headers['If-None-Match'] = options.headers['If-None-Match'];
219 }
220 > if (options.headers['If-Match']) { userDataSyncClient.ts
221 headers['If-Match'] = options.headers['If-Match'];
222 }
224 > this._requests.push({ url: options.url!, type: options.type!, headers });
225 > this._requestsWithAllHeaders.push({ url: options.url!, type: options.type!, headers: options.headers });
226 > const requestContext = await this.doRequest(options);
227 > this._responses.push({ status: requestContext.res.statusCode! });
228 > return requestContext;
229 > }
230
231 private async doRequest(options: IRequestOptions): Promise<IRequestContext> {
232 > const versionUrl = `${this.url}/v1/`; userDataSyncClient.ts
233 > const relativePath = options.url!.indexOf(versionUrl) === 0 ? options.url!.substring(versionUrl.length) : undefined;
234 > const segments = relativePath ? relativePath.split('/') : [];
235 > if (options.type === 'GET' && segments.length === 1 && segments[0] === 'manifest') {
236 return this.getManifest(options.headers);
237 }
238 > if (options.type === 'GET' && segments.length === 3 && segments[0] === 'resource') { userDataSyncClient.ts
239 return this.getResourceData(undefined, segments[1], segments[2] === 'latest' ? undefined : segments[2], options.headers);
240 }
241 > if (options.type === 'POST' && segments.length === 2 && segments[0] === 'resource') { userDataSyncClient.ts
242 return this.writeData(undefined, segments[1], options.data, options.headers);
243 }
244 // resources in collection
245 > if (options.type === 'GET' && segments.length === 5 && segments[0] === 'collection' && segments[2] === 'resource') { userDataSyncClient.ts
246 return this.getResourceData(segments[1], segments[3], segments[4] === 'latest' ? undefined : segments[4], options.headers);
247 }
248 > if (options.type === 'POST' && segments.length === 4 && segments[0] === 'collection' && segments[2] === 'resource') { userDataSyncClient.ts
249 return this.writeData(segments[1], segments[3], options.data, options.headers);
250 }
251 > if (options.type === 'DELETE' && segments.length === 2 && segments[0] === 'resource') { userDataSyncClient.ts
252 return this.deleteResourceData(undefined, segments[1]);
253 }
254 > if (options.type === 'DELETE' && segments.length === 1 && segments[0] === 'resource') { userDataSyncClient.ts
255 return this.clear(options.headers);
256 }
257 > if (options.type === 'DELETE' && segments[0] === 'collection') { userDataSyncClient.ts
258 return this.toResponse(204);
259 }
260 > if (options.type === 'POST' && segments.length === 1 && segments[0] === 'collection') { userDataSyncClient.ts
261 return this.createCollection();
262 }
263 return this.toResponse(501);
265
266 private async getManifest(headers?: IHeaders): Promise<IRequestContext> {
360
361 private toResponse(statusCode: number, headers?: IHeaders, data?: string): IRequestContext {
362 > return { userDataSyncClient.ts
363 > res: {
364 > headers: headers || {},
365 > statusCode
366 > },
367 > stream: bufferToStream(VSBuffer.fromString(data || ''))
368 > };
369 > }
370 }
371
394 class TestStorageService extends InMemoryStorageService {
395 constructor(private readonly profileStorageProfile: IUserDataProfile) {
396 > super(); userDataSyncClient.ts
397 > }
398 override hasScope(profile: IUserDataProfile): boolean {
399 return this.profileStorageProfile.id === profile.id;
src/vs/platform/userDataSync/common/userDataSync.ts 46 introduced LOC · 2 ranges

Open complete file

80
81 export function registerConfiguration(): IDisposable {
82 > const ignoredSettingsSchemaId = 'vscode://schemas/ignoredSettings'; userDataSync.ts
83 > const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
84 > configurationRegistry.registerConfiguration({
85 > id: 'settingsSync',
86 > order: 30,
87 > title: localize('settings sync', "Settings Sync"),
88 > type: 'object',
89 > properties: {
90 > [CONFIG_SYNC_KEYBINDINGS_PER_PLATFORM]: {
91 > type: 'boolean',
92 > description: localize('settingsSync.keybindingsPerPlatform', "Synchronize keybindings for each platform."),
93 > default: true,
94 > scope: ConfigurationScope.APPLICATION,
95 > tags: ['sync', 'usesOnlineServices']
96 > },
97 > 'settingsSync.ignoredExtensions': {
98 > 'type': 'array',
99 > markdownDescription: localize('settingsSync.ignoredExtensions', "List of extensions to be ignored while synchronizing. The identifier of an extension is always `${publisher}.${name}`. For example: `vscode.csharp`."),
100 > items: [{
101 > type: 'string',
102 > pattern: EXTENSION_IDENTIFIER_PATTERN,
103 > errorMessage: localize('app.extension.identifier.errorMessage', "Expected format '${publisher}.${name}'. Example: 'vscode.csharp'.")
104 > }],
105 > 'default': [],
106 > 'scope': ConfigurationScope.APPLICATION,
107 > uniqueItems: true,
108 > disallowSyncIgnore: true,
109 > tags: ['sync', 'usesOnlineServices']
110 > },
111 > 'settingsSync.ignoredSettings': {
112 > 'type': 'array',
113 > description: localize('settingsSync.ignoredSettings', "Configure settings to be ignored while synchronizing."),
114 > 'default': [],
115 > 'scope': ConfigurationScope.APPLICATION,
116 > $ref: ignoredSettingsSchemaId,
117 > additionalProperties: true,
118 > uniqueItems: true,
119 > disallowSyncIgnore: true,
120 > tags: ['sync', 'usesOnlineServices']
121 > }
122 > }
123 > });
124 > const jsonRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
125 > const registerIgnoredSettingsSchema = () => {
126 const disallowedIgnoredSettings = getDisallowedIgnoredSettings();
127 const defaultIgnoredSettings = getDefaultIgnoredSettings();
136 jsonRegistry.registerSchema(ignoredSettingsSchemaId, ignoredSettingsSchema);
137 };
138 > return configurationRegistry.onDidUpdateConfiguration(() => registerIgnoredSettingsSchema()); userDataSync.ts
139 > }
140
141 // #region User Data Sync Store
src/vs/platform/userDataSync/common/userDataSyncLocalStoreService.ts 35 introduced LOC · 9 ranges

Open complete file

21
22 constructor(
23 > @IEnvironmentService private readonly environmentService: IEnvironmentService, userDataSyncLocalStoreService.ts
24 > @IFileService private readonly fileService: IFileService,
25 > @IConfigurationService private readonly configurationService: IConfigurationService,
26 > @IUserDataSyncLogService private readonly logService: IUserDataSyncLogService,
27 > @IUserDataProfilesService private readonly userDataProfilesService: IUserDataProfilesService,
28 > ) {
29 > super();
30 > this.cleanUp();
31 > }
32
33 private async cleanUp(): Promise<void> {
34 > for (const profile of this.userDataProfilesService.profiles) { userDataSyncLocalStoreService.ts
35 > for (const resource of ALL_SYNC_RESOURCES) {
36 > try {
37 > await this.cleanUpBackup(this.getResourceBackupHome(resource, profile.isDefault ? undefined : profile.id));
38 > } catch (error) {
39 this.logService.error(error);
40 }
42 > }
43 >
44 > let stat: IFileStat;
45 > try {
46 > stat = await this.fileService.resolve(this.environmentService.userDataSyncHome);
47 > } catch (error) {
48 > if (toFileOperationResult(error) !== FileOperationResult.FILE_NOT_FOUND) {
49 this.logService.error(error);
50 }
52 > }
53
54 if (stat.children) {
64 }
65 }
67
68 async getAllResourceRefs(resource: SyncResource, collection?: string, root?: URI): Promise<IResourceRefHandle[]> {
108
109 private getResourceBackupHome(resource: SyncResource, collection?: string, root: URI = this.environmentService.userDataSyncHome): URI {
110 > return joinPath(root, ...(collection ? [collection, resource] : [resource])); userDataSyncLocalStoreService.ts
111 > }
112
113 private async cleanUpBackup(folder: URI): Promise<void> {
115 > try {
116 > if (!(await this.fileService.exists(folder))) {
117 > return;
118 > }
119 > } catch (e) {
120 return;
121 }
src/vs/platform/userDataSync/common/userDataSyncEnablementService.ts 26 introduced LOC · 6 ranges

Open complete file

24
25 constructor(
26 > @IStorageService private readonly storageService: IStorageService, userDataSyncEnablementService.ts
27 > @IEnvironmentService protected readonly environmentService: IEnvironmentService,
28 > @IUserDataSyncStoreManagementService private readonly userDataSyncStoreManagementService: IUserDataSyncStoreManagementService,
29 > ) {
30 > super();
31 > this._register(storageService.onDidChangeValue(StorageScope.APPLICATION, undefined, this._store)(e => this.onDidStorageChange(e)));
32 > }
33
34 isEnabled(): boolean {
54
55 isResourceEnabled(resource: SyncResource, defaultValue?: boolean): boolean {
56 > const storedValue = this.storageService.getBoolean(getEnablementKey(resource), StorageScope.APPLICATION); userDataSyncEnablementService.ts
57 > defaultValue = defaultValue ?? resource !== SyncResource.Prompts;
58 > return storedValue ?? defaultValue;
59 > }
60
61 isResourceEnablementConfigured(resource: SyncResource): boolean {
66
67 setResourceEnablement(resource: SyncResource, enabled: boolean): void {
68 > if (this.isResourceEnabled(resource) !== enabled) { userDataSyncEnablementService.ts
69 > const resourceEnablementKey = getEnablementKey(resource);
70 > this.storeResourceEnablement(resourceEnablementKey, enabled);
71 > }
72 > }
73
74 getResourceSyncStateVersion(resource: SyncResource): string | undefined {
77
78 private storeResourceEnablement(resourceEnablementKey: string, enabled: boolean): void {
79 > this.storageService.store(resourceEnablementKey, enabled, StorageScope.APPLICATION, isWeb ? StorageTarget.USER /* sync in web */ : StorageTarget.MACHINE); userDataSyncEnablementService.ts
80 > }
81
82 private onDidStorageChange(storageChangeEvent: IApplicationStorageValueChangeEvent): void {
83 > if (enablementKey === storageChangeEvent.key) { userDataSyncEnablementService.ts
84 this._onDidChangeEnablement.fire(this.isEnabled());
85 return;
86 }
88 > const resourceKey = ALL_SYNC_RESOURCES.filter(resourceKey => getEnablementKey(resourceKey) === storageChangeEvent.key)[0];
89 > if (resourceKey) {
90 > this._onDidChangeResourceEnablement.fire([resourceKey, this.isResourceEnabled(resourceKey)]);
91 > return;
92 > }
93 > }
94 }
src/vs/platform/userDataSync/common/userDataSyncService.ts 22 introduced LOC · 2 ranges

Open complete file

97
98 constructor(
99 > @IFileService private readonly fileService: IFileService, userDataSyncService.ts
100 > @IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService,
101 > @IUserDataSyncStoreManagementService private readonly userDataSyncStoreManagementService: IUserDataSyncStoreManagementService,
102 > @IInstantiationService private readonly instantiationService: IInstantiationService,
103 > @IUserDataSyncLogService private readonly logService: IUserDataSyncLogService,
104 > @ITelemetryService private readonly telemetryService: ITelemetryService,
105 > @IStorageService private readonly storageService: IStorageService,
106 > @IUserDataSyncEnablementService private readonly userDataSyncEnablementService: IUserDataSyncEnablementService,
107 > @IUserDataProfilesService private readonly userDataProfilesService: IUserDataProfilesService,
108 > @IUserDataSyncResourceProviderService private readonly userDataSyncResourceProviderService: IUserDataSyncResourceProviderService,
109 > @IUserDataSyncLocalStoreService private readonly userDataSyncLocalStoreService: IUserDataSyncLocalStoreService,
110 > ) {
111 > super();
112 > this._status = userDataSyncStoreManagementService.userDataSyncStore ? SyncStatus.Idle : SyncStatus.Uninitialized;
113 > this._lastSyncTime = this.storageService.getNumber(LAST_SYNC_TIME_KEY, StorageScope.APPLICATION, undefined);
114 > this._register(toDisposable(() => this.clearActiveProfileSynchronizers()));
115 >
116 > this._register(new RunOnceScheduler(() => this.cleanUpStaleStorageData(), 5 * 1000 /* after 5s */)).schedule();
117 > }
118
119 async createSyncTask(manifest: IUserDataManifest | null, disableCache?: boolean): Promise<IUserDataSyncTask> {
633
634 private clearActiveProfileSynchronizers(): void {
635 > this.activeProfileSynchronizers.forEach(([, disposable]) => disposable.dispose()); userDataSyncService.ts
636 > this.activeProfileSynchronizers.clear();
637 > }
638
639 private checkEnablement(): void {
src/vs/platform/userDataSync/common/userDataSyncAccount.ts 16 introduced LOC · 3 ranges

Open complete file

40
41 constructor(
42 > @IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService, userDataSyncAccount.ts
43 > @IUserDataSyncLogService private readonly logService: IUserDataSyncLogService,
44 > ) {
45 > super();
46 > this._register(userDataSyncStoreService.onTokenFailed(code => {
47 this.logService.info('Settings Sync auth token failed', this.account?.authenticationProviderId, this.wasTokenFailed, code);
48 this.updateAccount(undefined);
53 }
54 this.wasTokenFailed = true;
56 > this._register(userDataSyncStoreService.onTokenSucceed(() => this.wasTokenFailed = false));
57 > }
58
59 async updateAccount(account: IUserDataSyncAccount | undefined): Promise<void> {
60 > if (account && this._account ? account.token !== this._account.token || account.authenticationProviderId !== this._account.authenticationProviderId : account !== this._account) { userDataSyncAccount.ts
61 > this._account = account;
62 > if (this._account) {
63 > this.userDataSyncStoreService.setAuthToken(this._account.token, this._account.authenticationProviderId);
64 > }
65 > this._onDidChangeAccount.fire(account);
66 > }
67 > }
68
69 }
src/vs/platform/extensionManagement/common/extensionStorage.ts 13 introduced LOC · 3 ranges

Open complete file

77
78 private static readAllExtensionsWithKeysForSync(storageService: IStorageService): Map<string, string[]> {
79 > const extensionsWithKeysForSync = new Map<string, string[]>(); extensionStorage.ts
80 > const keys = storageService.keys(StorageScope.PROFILE, StorageTarget.MACHINE);
81 > for (const key of keys) {
82 const extensionIdWithVersion = ExtensionStorageService.fromKey(key);
83 if (extensionIdWithVersion) {
89 }
90 }
91 > return extensionsWithKeysForSync; extensionStorage.ts
92 > }
93
94 private readonly _onDidChangeExtensionStorageToSync = this._register(new Emitter<void>());
98
99 constructor(
100 > @IStorageService private readonly storageService: IStorageService, extensionStorage.ts
101 > @IProductService private readonly productService: IProductService,
102 > @ILogService private readonly logService: ILogService,
103 > ) {
104 > super();
105 > this.extensionsWithKeysForSync = ExtensionStorageService.readAllExtensionsWithKeysForSync(storageService);
106 > this._register(this.storageService.onDidChangeValue(StorageScope.PROFILE, undefined, this._store)(e => this.onDidChangeStorageValue(e)));
107 > }
108
109 private onDidChangeStorageValue(e: IProfileStorageValueChangeEvent): void {
src/vs/platform/extensionManagement/common/extensionEnablementService.ts 12 introduced LOC · 3 ranges

Open complete file

20
21 constructor(
22 > @IStorageService storageService: IStorageService, extensionEnablementService.ts
23 > @IExtensionManagementService extensionManagementService: IExtensionManagementService,
24 > ) {
25 > super();
26 > this.storageManager = this._register(new StorageManager(storageService));
27 > this._register(this.storageManager.onDidChange(extensions => this._onDidChangeEnablement.fire({ extensions, source: 'storage' })));
28 > this._register(extensionManagementService.onDidInstallExtensions(e => e.forEach(({ local, operation }) => {
29 if (local && operation === InstallOperation.Migrate) {
30 this._removeFromDisabledExtensions(local.identifier); /* Reset migrated extensions */
31 }
33 > }
34
35 async enableExtension(extension: IExtensionIdentifier, source?: string): Promise<boolean> {
102
103 constructor(private storageService: IStorageService) {
105 > this._register(storageService.onDidChangeValue(StorageScope.PROFILE, undefined, this._store)(e => this.onDidStorageChange(e)));
106 > }
107
108 get(key: string, scope: StorageScope): IExtensionIdentifier[] {
src/vs/platform/userDataSync/common/userDataSyncMachines.ts 10 introduced LOC · 1 range

Open complete file

89
90 constructor(
91 > @IEnvironmentService environmentService: IEnvironmentService, userDataSyncMachines.ts
92 > @IFileService fileService: IFileService,
93 > @IStorageService private readonly storageService: IStorageService,
94 > @IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService,
95 > @IUserDataSyncLogService private readonly logService: IUserDataSyncLogService,
96 > @IProductService private readonly productService: IProductService,
97 > ) {
98 > super();
99 > this.currentMachineIdPromise = getServiceMachineId(environmentService, fileService, storageService);
100 > }
101
102 async getMachines(manifest?: IUserDataManifest): Promise<IUserDataSyncMachine[]> {
src/vs/platform/userDataSync/common/ignoredExtensions.ts 3 introduced LOC · 1 range

Open complete file

26
27 constructor(
28 > @IConfigurationService private readonly configurationService: IConfigurationService, ignoredExtensions.ts
29 > ) {
30 > }
31
32 hasToNeverSyncExtension(extensionId: string): boolean {
src/vs/platform/externalServices/common/serviceMachineId.ts 2 introduced LOC · 1 range

Open complete file

28 await fileService.writeFile(environmentService.serviceMachineIdResource, VSBuffer.fromString(uuid));
29 } catch (error) {
30 > //noop serviceMachineId.ts
31 > }
32 }
33
src/vs/platform/request/common/request.ts 2 introduced LOC · 1 range

Open complete file

124
125 export function isSuccess(context: IRequestContext): boolean {
126 > return (context.res.statusCode && context.res.statusCode >= 200 && context.res.statusCode < 300) || context.res.statusCode === 1223; request.ts
127 > }
128
129 export function isClientError(context: IRequestContext): boolean {