Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions .eslint-allowed-bracket-notation-files
Original file line number Diff line number Diff line change
Expand Up @@ -463,18 +463,8 @@ src/vs/workbench/services/telemetry/common/workbenchCommonProperties.ts
src/vs/workbench/services/telemetry/test/browser/commonProperties.test.ts
src/vs/workbench/services/telemetry/test/node/commonProperties.test.ts

# Remote, tunnels, networking, and authentication (11 files)
# GitHub authentication service tests (1 file)
extensions/github-authentication/src/test/github.test.ts
extensions/microsoft-authentication/src/common/experimentation.ts
src/vs/platform/github/common/githubTransport.ts
src/vs/platform/remote/node/wsl.ts
src/vs/platform/request/node/requestService.ts
src/vs/platform/tunnel/node/tunnelProxy.ts
src/vs/platform/tunnel/test/node/tunnelProxy.test.ts
src/vs/platform/webContentExtractor/electron-main/webPageLoader.ts
src/vs/platform/webContentExtractor/test/electron-main/webPageLoader.test.ts
src/vs/workbench/contrib/remote/browser/remoteStartEntry.ts
src/vs/workbench/contrib/remoteTunnel/test/electron-browser/remoteTunnel.contribution.test.ts

# Language feature extensions (22 files)
extensions/css-language-features/client/src/node/cssClientMain.ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export async function createExperimentationService(
isPreRelease: boolean,
): Promise<IExperimentationService> {
const id = context.extension.id;
const version = context.extension.packageJSON['version'];
const version = context.extension.packageJSON.version;

const service = getExperimentationService(
id,
Expand Down
2 changes: 1 addition & 1 deletion src/vs/platform/github/common/githubTransport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ export class GitHubTransport extends Disposable implements IGitHubTransport {
'X-GitHub-Api-Version': defaultApiVersion,
};
if (authenticated) {
headers['Authorization'] = `Bearer ${token}`;
headers.Authorization = `Bearer ${token}`;
}
let response: Response;
try {
Expand Down
2 changes: 1 addition & 1 deletion src/vs/platform/remote/node/wsl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ async function testWSLFeatureInstalled(): Promise<boolean> {
}

function getSystem32Path(subPath: string): string | undefined {
const systemRoot = process.env['SystemRoot'];
const systemRoot = process.env.SystemRoot;
if (systemRoot) {
const is32ProcessOn64Windows = process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432');
return join(systemRoot, is32ProcessOn64Windows ? 'Sysnative' : 'System32', subPath);
Expand Down
4 changes: 2 additions & 2 deletions src/vs/platform/request/node/requestService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,10 @@ async function nodeRequestAttempt(options: NodeRequestOptions, token: Cancellati

const req = rawRequest(opts, (res: http.IncomingMessage) => {
const followRedirects: number = isNumber(options.followRedirects) ? options.followRedirects : 3;
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && followRedirects > 0 && res.headers['location']) {
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && followRedirects > 0 && res.headers.location) {
nodeRequest({
...options,
url: res.headers['location'],
url: res.headers.location,
followRedirects: followRedirects - 1
}, token).then(resolve, reject);
} else {
Expand Down
14 changes: 7 additions & 7 deletions src/vs/platform/tunnel/node/tunnelProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,21 +345,21 @@ export class TunnelProxy extends Disposable {
// An intermediary MUST parse the Connection header and remove any
// fields named in it, then remove Connection itself. It SHOULD
// also remove other known hop-by-hop headers.
const connectionTokens = (headers['connection'] ?? '')
const connectionTokens = (headers.connection ?? '')
.toString()
.split(',')
.map(t => t.trim().toLowerCase())
.filter(t => t.length > 0);
for (const token of connectionTokens) {
delete headers[token];
}
delete headers['connection'];
delete headers.connection;
delete headers['keep-alive'];
delete headers['proxy-authorization'];
delete headers['proxy-connection'];
delete headers['te'];
delete headers.te;
delete headers['transfer-encoding'];
delete headers['upgrade'];
delete headers.upgrade;

const proxyReq = http.request({
agent: this._tunnelAgent,
Expand Down Expand Up @@ -472,12 +472,12 @@ export class TunnelProxy extends Disposable {
// Handle IPv6 bracket notation [::1]:port
const bracketMatch = /^\[(?<host>[^\]]+)\]:(?<port>\d+)$/.exec(address);
if (bracketMatch?.groups) {
host = bracketMatch.groups['host'];
port = parseInt(bracketMatch.groups['port'], 10);
host = bracketMatch.groups.host;
port = parseInt(bracketMatch.groups.port, 10);
} else {
const bracketOnly = /^\[(?<host>[^\]]+)\]$/.exec(address);
if (bracketOnly?.groups) {
host = bracketOnly.groups['host'];
host = bracketOnly.groups.host;
port = defaultPort;
} else {
const lastColon = address.lastIndexOf(':');
Expand Down
4 changes: 2 additions & 2 deletions src/vs/platform/tunnel/test/node/tunnelProxy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,8 @@ suite('TunnelProxy', () => {
assert.strictEqual(forwarded['proxy-authorization'], undefined);
assert.strictEqual(forwarded['proxy-connection'], undefined);
assert.strictEqual(forwarded['keep-alive'], undefined);
assert.strictEqual(forwarded['te'], undefined);
assert.strictEqual(forwarded['upgrade'], undefined);
assert.strictEqual(forwarded.te, undefined);
assert.strictEqual(forwarded.upgrade, undefined);
// Headers named in Connection must also be removed
assert.strictEqual(forwarded['x-custom-hop'], undefined);
// Note: connection itself is replaced by Node's http.Agent with
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,13 +200,13 @@ export class WebPageLoader extends Disposable {
const headers = { ...details.requestHeaders };

// Request privacy for web-sites that respect these.
headers['DNT'] = '1';
headers.DNT = '1';
headers['Sec-GPC'] = '1';

// For the main document request, prefer markdown responses from sites that
// support agent-friendly content negotiation (e.g. Microsoft Learn, Cloudflare docs).
if (details.resourceType === 'mainFrame') {
headers['Accept'] = 'text/markdown, text/html;q=0.9, application/xhtml+xml;q=0.9, application/xml;q=0.8, */*;q=0.7';
headers.Accept = 'text/markdown, text/html;q=0.9, application/xhtml+xml;q=0.9, application/xml;q=0.8, */*;q=0.7';
}

callback({ requestHeaders: headers });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1279,11 +1279,11 @@ suite('WebPageLoader', () => {

// Verify privacy headers were added
assert.ok(modifiedHeaders);
assert.strictEqual(modifiedHeaders['DNT'], '1');
assert.strictEqual(modifiedHeaders.DNT, '1');
assert.strictEqual(modifiedHeaders['Sec-GPC'], '1');
assert.strictEqual(modifiedHeaders['TestHeader'], 'TestValue');
assert.strictEqual(modifiedHeaders.TestHeader, 'TestValue');
// Accept header should NOT be set for non-mainFrame requests
assert.strictEqual(modifiedHeaders['Accept'], undefined);
assert.strictEqual(modifiedHeaders.Accept, undefined);
});

test('onBeforeSendHeaders adds Accept header preferring markdown for mainFrame requests', () => {
Expand All @@ -1308,8 +1308,8 @@ suite('WebPageLoader', () => {
);

assert.ok(modifiedHeaders);
assert.ok(modifiedHeaders['Accept']?.includes('text/markdown'));
assert.ok(modifiedHeaders['Accept']?.includes('text/html'));
assert.ok(modifiedHeaders.Accept?.includes('text/markdown'));
assert.ok(modifiedHeaders.Accept?.includes('text/html'));
});

//#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class RemoteStartEntry extends Disposable implements IWorkbenchContributi

super();

const remoteExtensionTips = this.productService.remoteExtensionTips?.['tunnel'];
const remoteExtensionTips = this.productService.remoteExtensionTips?.tunnel;
this.startCommand = remoteExtensionTips?.startEntry?.startCommand ?? '';
this.remoteExtensionId = remoteExtensionTips?.extensionId ?? '';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,23 @@ import { ITunnelApplicationConfig } from '../../../../../base/common/product.js'
import { URI } from '../../../../../base/common/uri.js';
import { mock } from '../../../../../base/test/common/mock.js';
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';
import { IClipboardService } from '../../../../../platform/clipboard/common/clipboardService.js';
import { CommandsRegistry, ICommandService } from '../../../../../platform/commands/common/commands.js';
import { IDialogService } from '../../../../../platform/dialogs/common/dialogs.js';
import { INativeEnvironmentService } from '../../../../../platform/environment/common/environment.js';
import { TestInstantiationService } from '../../../../../platform/instantiation/test/common/instantiationServiceMock.js';
import { MockContextKeyService } from '../../../../../platform/keybinding/test/common/mockKeybindingService.js';
import { NullLoggerService } from '../../../../../platform/log/common/log.js';
import { INotificationService } from '../../../../../platform/notification/common/notification.js';
import { IProductService } from '../../../../../platform/product/common/productService.js';
import { IProgress, IProgressService, IProgressStep } from '../../../../../platform/progress/common/progress.js';
import { IQuickInputService, IQuickPick, IQuickPickItem } from '../../../../../platform/quickinput/common/quickInput.js';
import { INACTIVE_TUNNEL_MODE, IRemoteTunnelService, type ActiveTunnelMode, type TunnelStatus } from '../../../../../platform/remoteTunnel/common/remoteTunnel.js';
import { InMemoryStorageService } from '../../../../../platform/storage/common/storage.js';
import { InMemoryStorageService, IStorageService } from '../../../../../platform/storage/common/storage.js';
import { IWorkspaceContextService } from '../../../../../platform/workspace/common/workspace.js';
import { IAuthenticationProvider, AuthenticationSession, IAuthenticationService } from '../../../../services/authentication/common/authentication.js';
import { ICommandService } from '../../../../../platform/commands/common/commands.js';
import { IExtensionService } from '../../../../services/extensions/common/extensions.js';
import { RemoteTunnelWorkbenchContribution } from '../../electron-browser/remoteTunnel.contribution.js';
import { RemoteTunnelCommandIds, RemoteTunnelWorkbenchContribution } from '../../electron-browser/remoteTunnel.contribution.js';

const tunnelApplicationConfig: ITunnelApplicationConfig = {
authenticationProviders: {
Expand Down Expand Up @@ -134,31 +136,62 @@ class TestProgressService extends mock<IProgressService>() {
}
}

class TestDialogService extends mock<IDialogService>() { }
class TestDialogService extends mock<IDialogService>() {
override async confirm(): Promise<{ confirmed: boolean }> {
return { confirmed: true };
}
}
class TestClipboardService extends mock<IClipboardService>() { }
class TestCommandService extends mock<ICommandService>() { }
class TestWorkspaceContextService extends mock<IWorkspaceContextService>() { }
class TestNotificationService extends mock<INotificationService>() { }

function createContribution(store: Pick<DisposableStore, 'add'>, authenticationService: TestAuthenticationService, quickInputService: TestQuickInputService, remoteTunnelService: TestRemoteTunnelService): RemoteTunnelWorkbenchContribution {
return store.add(new RemoteTunnelWorkbenchContribution(
function createContribution(store: Pick<DisposableStore, 'add'>, authenticationService: TestAuthenticationService, quickInputService: TestQuickInputService, remoteTunnelService: TestRemoteTunnelService): TestInstantiationService {
const dialogService = new TestDialogService();
const productService = new class extends mock<IProductService>() {
override readonly tunnelApplicationName = 'Code';
override readonly tunnelApplicationConfig = tunnelApplicationConfig;
};
const storageService = store.add(new InMemoryStorageService());
const commandService = new TestCommandService();
const notificationService = new TestNotificationService();

store.add(new RemoteTunnelWorkbenchContribution(
authenticationService,
new TestDialogService(),
dialogService,
new TestExtensionService(),
store.add(new MockContextKeyService()),
new class extends mock<IProductService>() {
override readonly tunnelApplicationName = 'Code';
override readonly tunnelApplicationConfig = tunnelApplicationConfig;
},
store.add(new InMemoryStorageService()),
productService,
storageService,
store.add(new NullLoggerService()),
quickInputService,
new TestEnvironmentService(),
remoteTunnelService,
new TestCommandService(),
commandService,
new TestWorkspaceContextService(),
new TestProgressService(),
new TestNotificationService(),
notificationService,
));

const instantiationService = store.add(new TestInstantiationService());
instantiationService.set(INotificationService, notificationService);
instantiationService.set(IClipboardService, new TestClipboardService());
instantiationService.set(ICommandService, commandService);
instantiationService.set(IStorageService, storageService);
instantiationService.set(IDialogService, dialogService);
instantiationService.set(IQuickInputService, quickInputService);
instantiationService.set(IProductService, productService);
return instantiationService;
}

async function startTunnel(instantiationService: TestInstantiationService): Promise<void> {
const command = CommandsRegistry.getCommand(RemoteTunnelCommandIds.turnOn);
assert.ok(command);
await instantiationService.invokeFunction(command.handler, {
authenticationProviderId: 'github',
showServiceOption: false,
showSuccessNotification: false,
});
}

suite('RemoteTunnelWorkbenchContribution', () => {
Expand All @@ -168,9 +201,9 @@ suite('RemoteTunnelWorkbenchContribution', () => {
const authenticationService = new TestAuthenticationService([githubSession]);
const quickInputService = new TestQuickInputService();
const remoteTunnelService = new TestRemoteTunnelService();
const contribution = createContribution(store, authenticationService, quickInputService, remoteTunnelService);
const instantiationService = createContribution(store, authenticationService, quickInputService, remoteTunnelService);

await contribution['startTunnel'](false, 'github');
await startTunnel(instantiationService);

assert.deepStrictEqual({
quickPickCalls: quickInputService.createQuickPickCalls,
Expand Down Expand Up @@ -198,9 +231,9 @@ suite('RemoteTunnelWorkbenchContribution', () => {
const authenticationService = new TestAuthenticationService([]);
const quickInputService = new TestQuickInputService();
const remoteTunnelService = new TestRemoteTunnelService();
const contribution = createContribution(store, authenticationService, quickInputService, remoteTunnelService);
const instantiationService = createContribution(store, authenticationService, quickInputService, remoteTunnelService);

await contribution['startTunnel'](false, 'github');
await startTunnel(instantiationService);

assert.deepStrictEqual({
quickPickCalls: quickInputService.createQuickPickCalls,
Expand Down