Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream' into include_modern_net_flag
Browse files Browse the repository at this point in the history
  • Loading branch information
dibarbet committed Mar 11, 2023
2 parents eceefa8 + ed84442 commit d7240c3
Show file tree
Hide file tree
Showing 13 changed files with 528 additions and 23 deletions.
15 changes: 15 additions & 0 deletions debugger-launchjson.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,3 +338,18 @@ Example:
```json
"targetArchitecture": "arm64"
```

## Check for DevCert

This option controls if, on launch, the the debugger should check if the computer has a self-signed HTTPS certificate used to develop web projects running on https endpoints. For this it will try to run `dotnet dev-certs https --check --trust`, if no certs are found it will prompt the user to suggest creating one. If approved by the user, the extension will run `dotnet dev-certs https --trust` to create a trusted self-signed certificate.

If unspecified, defaults to true when `serverReadyAction` is set.
This option does nothing on Linux, VS Code remote, and VS Code Web UI scenarios.

You can override this behavior by setting `checkForDevCert` to false in your `launch.json`.

Example:

```json
"checkForDevCert": "false"
```
10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1982,6 +1982,11 @@
"targetArchitecture": {
"type": "string",
"description": "[Only supported in local macOS debugging] The architecture of the debuggee. This will automatically be detected unless this parameter is set. Allowed values are x86_64 or arm64."
},
"checkForDevCert": {
"type": "boolean",
"description": "When true, the debugger will check if the computer has a self-signed HTTPS certificate used to develop web servers running on https endpoints. If unspecified, defaults to true when `serverReadyAction` is set. This option does nothing on Linux, VS Code remote, and VS Code Web UI scenarios. If the HTTPS certificate is not found or isn't trusted, the user will be prompted to install/trust it.",
"default": true
}
}
},
Expand Down Expand Up @@ -3109,6 +3114,11 @@
"targetArchitecture": {
"type": "string",
"description": "[Only supported in local macOS debugging] The architecture of the debuggee. This will automatically be detected unless this parameter is set. Allowed values are x86_64 or arm64."
},
"checkForDevCert": {
"type": "boolean",
"description": "When true, the debugger will check if the computer has a self-signed HTTPS certificate used to develop web servers running on https endpoints. If unspecified, defaults to true when `serverReadyAction` is set. This option does nothing on Linux, VS Code remote, and VS Code Web UI scenarios. If the HTTPS certificate is not found or isn't trusted, the user will be prompted to install/trust it.",
"default": true
}
}
},
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr-debug/activate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ export async function activate(thisExtension: vscode.Extension<CSharpExtensionEx
}

const factory = new DebugAdapterExecutableFactory(debugUtil, platformInformation, eventStream, thisExtension.packageJSON, thisExtension.extensionPath, options);
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('coreclr', new DotnetDebugConfigurationProvider(platformInformation)));
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('clr', new DotnetDebugConfigurationProvider(platformInformation)));
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('coreclr', new DotnetDebugConfigurationProvider(platformInformation, eventStream, options)));
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('clr', new DotnetDebugConfigurationProvider(platformInformation, eventStream, options)));
context.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory('coreclr', factory));
context.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory('clr', factory));
}
Expand Down
67 changes: 65 additions & 2 deletions src/coreclr-debug/debugConfigurationProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@
import * as vscode from 'vscode';

import { RemoteAttachPicker, DotNetAttachItemsProviderFactory, AttachPicker, AttachItem } from '../features/processPicker';
import { Options } from '../omnisharp/options';
import { PlatformInformation } from '../platform';

import { hasDotnetDevCertsHttps, createSelfSignedCert, CertToolStatusCodes } from '../utils/DotnetDevCertsHttps';
import { EventStream } from '../EventStream';
import { DevCertCreationFailure, ShowChannel } from '../omnisharp/loggingEvents';

export class DotnetDebugConfigurationProvider implements vscode.DebugConfigurationProvider {
constructor(public platformInformation: PlatformInformation) {}
constructor(public platformInformation: PlatformInformation, private readonly eventStream: EventStream, private options: Options) {}

public async resolveDebugConfigurationWithSubstitutedVariables(folder: vscode.WorkspaceFolder | undefined, debugConfiguration: vscode.DebugConfiguration, token?: vscode.CancellationToken): Promise<vscode.DebugConfiguration | null | undefined>
{
Expand Down Expand Up @@ -59,7 +63,66 @@ export class DotnetDebugConfigurationProvider implements vscode.DebugConfigurati
return undefined;
}
}

// We want to ask the user if we should run dotnet dev-certs https --trust, but this doesn't work in a few cases --
// Linux -- not supported by the .NET CLI as there isn't a single root cert store
// VS Code remoting/Web UI -- the trusted cert work would need to happen on the client machine, but we don't have a way to run code there currently
// pipeTransport -- the dev cert on the server will be different from the client
if (!this.platformInformation.isLinux() && !vscode.env.remoteName && vscode.env.uiKind != vscode.UIKind.Web && !debugConfiguration.pipeTransport)
{
if(debugConfiguration.checkForDevCert === undefined && debugConfiguration.serverReadyAction)
{
debugConfiguration.checkForDevCert = true;
}

if (debugConfiguration.checkForDevCert)
{
checkForDevCerts(this.options.dotNetCliPaths, this.eventStream);
}
}

return debugConfiguration;
}
}

function checkForDevCerts(dotNetCliPaths: string[], eventStream: EventStream){
hasDotnetDevCertsHttps(dotNetCliPaths).then(async (returnData) => {
let errorCode = returnData.error?.code;
if(errorCode === CertToolStatusCodes.CertificateNotTrusted || errorCode === CertToolStatusCodes.ErrorNoValidCertificateFound)
{
const labelYes: string = "Yes";
const labelNotNow: string = "Not Now";
const labelMoreInfo: string = "More Information";

const result = await vscode.window.showInformationMessage(
"The selected launch configuration is configured to launch a web browser but no trusted development certificate was found. Create a trusted self-signed certificate?",
{ title:labelYes }, { title:labelNotNow, isCloseAffordance: true }, { title:labelMoreInfo }
);
if (result?.title === labelYes)
{
let returnData = await createSelfSignedCert(dotNetCliPaths);
if (returnData.error === null) //if the prcess returns 0, returnData.error is null, otherwise the return code can be acessed in returnData.error.code
{
let message = errorCode === CertToolStatusCodes.CertificateNotTrusted ? 'trusted' : 'created';
vscode.window.showInformationMessage(`Self-signed certificate sucessfully ${message}.`);
}
else
{
eventStream.post(new DevCertCreationFailure(`${returnData.error.message}\ncode: ${returnData.error.code}\nstdout: ${returnData.stdout}`));

const labelShowOutput: string = "Show Output";
const result = await vscode.window.showWarningMessage("Couldn't create self-signed certificate. See output for more information.", labelShowOutput);
if (result === labelShowOutput){
eventStream.post(new ShowChannel());
}
}
}
if (result?.title === labelMoreInfo)
{
const launchjsonDescriptionURL = 'https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#check-for-devcert';
vscode.env.openExternal(vscode.Uri.parse(launchjsonDescriptionURL));
checkForDevCerts(dotNetCliPaths, eventStream);
}
}
});
}
42 changes: 37 additions & 5 deletions src/features/documentSymbolProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ export default class OmnisharpDocumentSymbolProvider extends AbstractSupport imp
}
}

function createSymbols(elements: Structure.CodeElement[]): vscode.DocumentSymbol[] {
function createSymbols(elements: Structure.CodeElement[], parentElement?: Structure.CodeElement): vscode.DocumentSymbol[] {
let results: vscode.DocumentSymbol[] = [];

elements.forEach(element => {
let symbol = createSymbolForElement(element);
let symbol = createSymbolForElement(element, parentElement);
if (element.Children) {
symbol.children = createSymbols(element.Children);
symbol.children = createSymbols(element.Children, element);
}

results.push(symbol);
Expand All @@ -46,11 +46,43 @@ function createSymbols(elements: Structure.CodeElement[]): vscode.DocumentSymbol
return results;
}

function createSymbolForElement(element: Structure.CodeElement): vscode.DocumentSymbol {
function getNameForElement(element: Structure.CodeElement, parentElement?: Structure.CodeElement): string {
switch (element.Kind) {
case SymbolKinds.Class:
case SymbolKinds.Delegate:
case SymbolKinds.Enum:
case SymbolKinds.Interface:
case SymbolKinds.Struct:
return element.Name;

case SymbolKinds.Namespace:
return typeof parentElement !== 'undefined' && element.DisplayName.startsWith(`${parentElement.DisplayName}.`)
? element.DisplayName.slice(parentElement.DisplayName.length + 1)
: element.DisplayName;

case SymbolKinds.Constant:
case SymbolKinds.Constructor:
case SymbolKinds.Destructor:
case SymbolKinds.EnumMember:
case SymbolKinds.Event:
case SymbolKinds.Field:
case SymbolKinds.Indexer:
case SymbolKinds.Method:
case SymbolKinds.Operator:
case SymbolKinds.Property:
case SymbolKinds.Unknown:
default:
return element.DisplayName;
}
}

function createSymbolForElement(element: Structure.CodeElement, parentElement?: Structure.CodeElement): vscode.DocumentSymbol {
const fullRange = element.Ranges[SymbolRangeNames.Full];
const nameRange = element.Ranges[SymbolRangeNames.Name];
const name = getNameForElement(element, parentElement);
const details = name === element.DisplayName ? '' : element.DisplayName;

return new vscode.DocumentSymbol(element.DisplayName, /*detail*/ "", toSymbolKind(element.Kind), toRange3(fullRange), toRange3(nameRange));
return new vscode.DocumentSymbol(name, details, toSymbolKind(element.Kind), toRange3(fullRange), toRange3(nameRange));
}

const kinds: { [kind: string]: vscode.SymbolKind; } = {};
Expand Down
3 changes: 3 additions & 0 deletions src/observers/CsharpChannelObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ export class CsharpChannelObserver extends BaseChannelObserver {
case EventType.ProjectJsonDeprecatedWarning:
this.showChannel(true);
break;
case EventType.ShowChannel:
this.showChannel(false);
break;
}
}
}
7 changes: 7 additions & 0 deletions src/observers/CsharpLoggerObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ export class CsharpLoggerObserver extends BaseLoggerObserver {
case EventType.IntegrityCheckSuccess:
this.handleIntegrityCheckSuccess(<Event.IntegrityCheckSuccess>event);
break;
case EventType.DevCertCreationFailure:
this.handleDevCertCreationFailure(<Event.DevCertCreationFailure>event);
break;
}
}

Expand Down Expand Up @@ -146,4 +149,8 @@ export class CsharpLoggerObserver extends BaseLoggerObserver {
private handleDocumentSynchronizationFailure(event: Event.DocumentSynchronizationFailure) {
this.logger.appendLine(`Failed to synchronize document '${event.documentPath}': ${event.errorMessage}`);
}

private handleDevCertCreationFailure(event: Event.DevCertCreationFailure) {
this.logger.appendLine(`Couldn't create self-signed certificate. ${event.errorMessage}`);
}
}
2 changes: 2 additions & 0 deletions src/omnisharp/EventType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ export enum EventType {
TelemetryErrorEvent = 78,
OmnisharpServerRequestCancelled = 79,
BackgroundDiagnosticStatus = 80,
DevCertCreationFailure = 81,
ShowChannel = 82,
}

//Note that the EventType protocol is shared with Razor.VSCode and the numbers here should not be altered
Expand Down
7 changes: 7 additions & 0 deletions src/omnisharp/loggingEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,3 +350,10 @@ export class DotNetTestDebugComplete implements BaseEvent {
export class DownloadValidation implements BaseEvent {
type = EventType.DownloadValidation;
}
export class DevCertCreationFailure implements BaseEvent {
type = EventType.DevCertCreationFailure;
constructor(public errorMessage: string) { }
}
export class ShowChannel implements BaseEvent {
type = EventType.ShowChannel;
}
Loading

0 comments on commit d7240c3

Please sign in to comment.