Skip to content

Commit 04eca07

Browse files
authored
Add configurable extension requests timeout setting (#274761)
1 parent e8f3336 commit 04eca07

File tree

3 files changed

+20
-8
lines changed

3 files changed

+20
-8
lines changed

src/vs/platform/extensionManagement/common/extensionGalleryService.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ import { CancellationError, getErrorMessage, isCancellationError } from '../../.
1111
import { IPager } from '../../../base/common/paging.js';
1212
import { isWeb, platform } from '../../../base/common/platform.js';
1313
import { arch } from '../../../base/common/process.js';
14-
import { isBoolean, isString } from '../../../base/common/types.js';
14+
import { isBoolean, isNumber, isString } from '../../../base/common/types.js';
1515
import { URI } from '../../../base/common/uri.js';
1616
import { IHeaders, IRequestContext, IRequestOptions, isOfflineError } from '../../../base/parts/request/common/request.js';
1717
import { IConfigurationService } from '../../configuration/common/configuration.js';
1818
import { IEnvironmentService } from '../../environment/common/environment.js';
19-
import { getTargetPlatform, IExtensionGalleryService, IExtensionIdentifier, IExtensionInfo, IGalleryExtension, IGalleryExtensionAsset, IGalleryExtensionAssets, IGalleryExtensionVersion, InstallOperation, IQueryOptions, IExtensionsControlManifest, isNotWebExtensionInWebTargetPlatform, isTargetPlatformCompatible, ITranslation, SortOrder, StatisticType, toTargetPlatform, WEB_EXTENSION_TAG, IExtensionQueryOptions, IDeprecationInfo, ISearchPrefferedResults, ExtensionGalleryError, ExtensionGalleryErrorCode, IProductVersion, IAllowedExtensionsService, EXTENSION_IDENTIFIER_REGEX, SortBy, FilterType, MaliciousExtensionInfo } from './extensionManagement.js';
19+
import { getTargetPlatform, IExtensionGalleryService, IExtensionIdentifier, IExtensionInfo, IGalleryExtension, IGalleryExtensionAsset, IGalleryExtensionAssets, IGalleryExtensionVersion, InstallOperation, IQueryOptions, IExtensionsControlManifest, isNotWebExtensionInWebTargetPlatform, isTargetPlatformCompatible, ITranslation, SortOrder, StatisticType, toTargetPlatform, WEB_EXTENSION_TAG, IExtensionQueryOptions, IDeprecationInfo, ISearchPrefferedResults, ExtensionGalleryError, ExtensionGalleryErrorCode, IProductVersion, IAllowedExtensionsService, EXTENSION_IDENTIFIER_REGEX, SortBy, FilterType, MaliciousExtensionInfo, ExtensionRequestsTimeoutConfigKey } from './extensionManagement.js';
2020
import { adoptToGalleryExtensionId, areSameExtensions, getGalleryExtensionId, getGalleryExtensionTelemetryData } from './extensionManagementUtil.js';
2121
import { IExtensionManifest, TargetPlatform } from '../../extensions/common/extensions.js';
2222
import { areApiProposalsCompatible, isEngineValid } from '../../extensions/common/extensionValidator.js';
@@ -37,7 +37,6 @@ const SEARCH_ACTIVITY_HEADER_NAME = 'X-Market-Search-Activity-Id';
3737
const ACTIVITY_HEADER_NAME = 'Activityid';
3838
const SERVER_HEADER_NAME = 'Server';
3939
const END_END_ID_HEADER_NAME = 'X-Vss-E2eid';
40-
const REQUEST_TIME_OUT = 10_000;
4140

4241
interface IRawGalleryExtensionFile {
4342
readonly assetType: string;
@@ -1452,7 +1451,7 @@ export abstract class AbstractExtensionGalleryService implements IExtensionGalle
14521451
type: 'GET',
14531452
url: uri.toString(true),
14541453
headers,
1455-
timeout: REQUEST_TIME_OUT
1454+
timeout: this.getRequestTimeout()
14561455
}, token);
14571456

14581457
if (context.res.statusCode === 404) {
@@ -1745,7 +1744,7 @@ export abstract class AbstractExtensionGalleryService implements IExtensionGalle
17451744

17461745
const url = asset.uri;
17471746
const fallbackUrl = asset.fallbackUri;
1748-
const firstOptions = { ...options, url, timeout: REQUEST_TIME_OUT };
1747+
const firstOptions = { ...options, url, timeout: this.getRequestTimeout() };
17491748

17501749
let context;
17511750
try {
@@ -1791,7 +1790,7 @@ export abstract class AbstractExtensionGalleryService implements IExtensionGalle
17911790
endToEndId: this.getHeaderValue(context?.res.headers, END_END_ID_HEADER_NAME),
17921791
});
17931792

1794-
const fallbackOptions = { ...options, url: fallbackUrl, timeout: REQUEST_TIME_OUT };
1793+
const fallbackOptions = { ...options, url: fallbackUrl, timeout: this.getRequestTimeout() };
17951794
return this.requestService.request(fallbackOptions, token);
17961795
}
17971796
}
@@ -1810,7 +1809,7 @@ export abstract class AbstractExtensionGalleryService implements IExtensionGalle
18101809
const context = await this.requestService.request({
18111810
type: 'GET',
18121811
url: this.extensionsControlUrl,
1813-
timeout: REQUEST_TIME_OUT
1812+
timeout: this.getRequestTimeout()
18141813
}, CancellationToken.None);
18151814

18161815
if (context.res.statusCode !== 200) {
@@ -1862,6 +1861,11 @@ export abstract class AbstractExtensionGalleryService implements IExtensionGalle
18621861
return { malicious, deprecated, search, autoUpdate };
18631862
}
18641863

1864+
private getRequestTimeout(): number {
1865+
const configuredTimeout = this.configurationService.getValue<number>(ExtensionRequestsTimeoutConfigKey);
1866+
return isNumber(configuredTimeout) && configuredTimeout >= 0 ? configuredTimeout : 60_000;
1867+
}
1868+
18651869
}
18661870

18671871
export class ExtensionGalleryService extends AbstractExtensionGalleryService {

src/vs/platform/extensionManagement/common/extensionManagement.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,7 @@ export const ExtensionsLocalizedLabel = localize2('extensions', "Extensions");
710710
export const PreferencesLocalizedLabel = localize2('preferences', 'Preferences');
711711
export const AllowedExtensionsConfigKey = 'extensions.allowed';
712712
export const VerifyExtensionSignatureConfigKey = 'extensions.verifySignature';
713+
export const ExtensionRequestsTimeoutConfigKey = 'extensions.requestTimeout';
713714

714715
Registry.as<IConfigurationRegistry>(Extensions.Configuration)
715716
.registerConfiguration({

src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurati
2626
import { ContextKeyExpr, IContextKeyService, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js';
2727
import { IDialogService, IFileDialogService } from '../../../../platform/dialogs/common/dialogs.js';
2828
import { ExtensionGalleryManifestStatus, ExtensionGalleryResourceType, ExtensionGalleryServiceUrlConfigKey, getExtensionGalleryManifestResourceUri, IExtensionGalleryManifest, IExtensionGalleryManifestService } from '../../../../platform/extensionManagement/common/extensionGalleryManifest.js';
29-
import { EXTENSION_INSTALL_SOURCE_CONTEXT, ExtensionInstallSource, ExtensionsLocalizedLabel, FilterType, IExtensionGalleryService, IExtensionManagementService, PreferencesLocalizedLabel, SortBy, VerifyExtensionSignatureConfigKey } from '../../../../platform/extensionManagement/common/extensionManagement.js';
29+
import { EXTENSION_INSTALL_SOURCE_CONTEXT, ExtensionInstallSource, ExtensionRequestsTimeoutConfigKey, ExtensionsLocalizedLabel, FilterType, IExtensionGalleryService, IExtensionManagementService, PreferencesLocalizedLabel, SortBy, VerifyExtensionSignatureConfigKey } from '../../../../platform/extensionManagement/common/extensionManagement.js';
3030
import { areSameExtensions, getIdAndVersion } from '../../../../platform/extensionManagement/common/extensionManagementUtil.js';
3131
import { ExtensionStorageService } from '../../../../platform/extensionManagement/common/extensionStorage.js';
3232
import { IExtensionRecommendationNotificationService } from '../../../../platform/extensionRecommendations/common/extensionRecommendations.js';
@@ -302,6 +302,13 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
302302
description: localize('extensionsSupportNodeGlobalNavigator', "When enabled, Node.js navigator object is exposed on the global scope."),
303303
default: false,
304304
},
305+
[ExtensionRequestsTimeoutConfigKey]: {
306+
type: 'number',
307+
description: localize('extensionsRequestTimeout', "Controls the timeout in milliseconds for HTTP requests made when fetching extensions from the Marketplace"),
308+
default: 60_000,
309+
scope: ConfigurationScope.APPLICATION,
310+
tags: ['advanced', 'usesOnlineServices']
311+
},
305312
}
306313
});
307314

0 commit comments

Comments
 (0)