Merge commit 'be3e8236086165e5e45a5a10783823874b3f3ebd' as 'lib/vscode'

This commit is contained in:
Joe Previte
2020-12-15 15:52:33 -07:00
4649 changed files with 1311795 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
<!-- Copyright (C) Microsoft Corporation. All rights reserved. -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data:; media-src 'none'; child-src 'self'; object-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; font-src 'self' https:;">
<style>
body {
display: none
}
</style>
</head>
<body aria-label="">
</body>
<!-- Init Bootstrap Helpers -->
<script src="../../../../bootstrap.js"></script>
<script src="../../../../vs/loader.js"></script>
<script src="../../../../bootstrap-window.js"></script>
<!-- Startup via issueReporter.js -->
<script src="issueReporter.js"></script>
</html>

View File

@@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
//@ts-check
'use strict';
(function () {
const bootstrapWindow = bootstrapWindowLib();
// Load issue reporter into window
bootstrapWindow.load(['vs/code/electron-sandbox/issue/issueReporterMain'], function (issueReporter, configuration) {
issueReporter.startup(configuration);
}, { forceEnableDeveloperKeybindings: true, disallowReloadKeybinding: true });
//#region Globals
/**
* @returns {{ load: (modules: string[], resultCallback: (result, configuration: object) => any, options?: object) => unknown }}
*/
function bootstrapWindowLib() {
// @ts-ignore (defined in bootstrap-window.js)
return window.MonacoBootstrapWindow;
}
//#endregion
}());

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,235 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IssueType, ISettingSearchResult, IssueReporterExtensionData } from 'vs/platform/issue/common/issue';
import { SystemInfo, isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
export interface IssueReporterData {
issueType: IssueType;
issueDescription?: string;
versionInfo?: any;
systemInfo?: SystemInfo;
processInfo?: any;
workspaceInfo?: any;
includeSystemInfo: boolean;
includeWorkspaceInfo: boolean;
includeProcessInfo: boolean;
includeExtensions: boolean;
includeSearchedExtensions: boolean;
includeSettingsSearchDetails: boolean;
numberOfThemeExtesions?: number;
allExtensions: IssueReporterExtensionData[];
enabledNonThemeExtesions?: IssueReporterExtensionData[];
extensionsDisabled?: boolean;
fileOnExtension?: boolean;
selectedExtension?: IssueReporterExtensionData;
actualSearchResults?: ISettingSearchResult[];
query?: string;
filterResultCount?: number;
}
export class IssueReporterModel {
private readonly _data: IssueReporterData;
constructor(initialData?: Partial<IssueReporterData>) {
const defaultData = {
issueType: IssueType.Bug,
includeSystemInfo: true,
includeWorkspaceInfo: true,
includeProcessInfo: true,
includeExtensions: true,
includeSearchedExtensions: true,
includeSettingsSearchDetails: true,
allExtensions: []
};
this._data = initialData ? Object.assign(defaultData, initialData) : defaultData;
}
getData(): IssueReporterData {
return this._data;
}
update(newData: Partial<IssueReporterData>): void {
Object.assign(this._data, newData);
}
serialize(): string {
return `
Issue Type: <b>${this.getIssueTypeTitle()}</b>
${this._data.issueDescription}
${this.getExtensionVersion()}
VS Code version: ${this._data.versionInfo && this._data.versionInfo.vscodeVersion}
OS version: ${this._data.versionInfo && this._data.versionInfo.os}
${this.getRemoteOSes()}
${this.getInfos()}
<!-- generated by issue reporter -->`;
}
private getRemoteOSes(): string {
if (this._data.systemInfo && this._data.systemInfo.remoteData.length) {
return this._data.systemInfo.remoteData
.map(remote => isRemoteDiagnosticError(remote) ? remote.errorMessage : `Remote OS version: ${remote.machineInfo.os}`).join('\n') + '\n';
}
return '';
}
fileOnExtension(): boolean | undefined {
const fileOnExtensionSupported = this._data.issueType === IssueType.Bug
|| this._data.issueType === IssueType.PerformanceIssue
|| this._data.issueType === IssueType.FeatureRequest;
return fileOnExtensionSupported && this._data.fileOnExtension;
}
private getExtensionVersion(): string {
if (this.fileOnExtension() && this._data.selectedExtension) {
return `\nExtension version: ${this._data.selectedExtension.version}`;
} else {
return '';
}
}
private getIssueTypeTitle(): string {
if (this._data.issueType === IssueType.Bug) {
return 'Bug';
} else if (this._data.issueType === IssueType.PerformanceIssue) {
return 'Performance Issue';
} else {
return 'Feature Request';
}
}
private getInfos(): string {
let info = '';
if (this._data.issueType === IssueType.Bug || this._data.issueType === IssueType.PerformanceIssue) {
if (this._data.includeSystemInfo && this._data.systemInfo) {
info += this.generateSystemInfoMd();
}
}
if (this._data.issueType === IssueType.PerformanceIssue) {
if (this._data.includeProcessInfo) {
info += this.generateProcessInfoMd();
}
if (this._data.includeWorkspaceInfo) {
info += this.generateWorkspaceInfoMd();
}
}
if (this._data.issueType === IssueType.Bug || this._data.issueType === IssueType.PerformanceIssue) {
if (!this._data.fileOnExtension && this._data.includeExtensions) {
info += this.generateExtensionsMd();
}
}
return info;
}
private generateSystemInfoMd(): string {
let md = `<details>
<summary>System Info</summary>
|Item|Value|
|---|---|
`;
if (this._data.systemInfo) {
md += `|CPUs|${this._data.systemInfo.cpus}|
|GPU Status|${Object.keys(this._data.systemInfo.gpuStatus).map(key => `${key}: ${this._data.systemInfo!.gpuStatus[key]}`).join('<br>')}|
|Load (avg)|${this._data.systemInfo.load}|
|Memory (System)|${this._data.systemInfo.memory}|
|Process Argv|${this._data.systemInfo.processArgs}|
|Screen Reader|${this._data.systemInfo.screenReader}|
|VM|${this._data.systemInfo.vmHint}|`;
if (this._data.systemInfo.linuxEnv) {
md += `\n|DESKTOP_SESSION|${this._data.systemInfo.linuxEnv.desktopSession}|
|XDG_CURRENT_DESKTOP|${this._data.systemInfo.linuxEnv.xdgCurrentDesktop}|
|XDG_SESSION_DESKTOP|${this._data.systemInfo.linuxEnv.xdgSessionDesktop}|
|XDG_SESSION_TYPE|${this._data.systemInfo.linuxEnv.xdgSessionType}|`;
}
this._data.systemInfo.remoteData.forEach(remote => {
if (isRemoteDiagnosticError(remote)) {
md += `\n\n${remote.errorMessage}`;
} else {
md += `
|Item|Value|
|---|---|
|Remote|${remote.hostName}|
|OS|${remote.machineInfo.os}|
|CPUs|${remote.machineInfo.cpus}|
|Memory (System)|${remote.machineInfo.memory}|
|VM|${remote.machineInfo.vmHint}|`;
}
});
}
md += '\n</details>';
return md;
}
private generateProcessInfoMd(): string {
return `<details>
<summary>Process Info</summary>
\`\`\`
${this._data.processInfo}
\`\`\`
</details>
`;
}
private generateWorkspaceInfoMd(): string {
return `<details>
<summary>Workspace Info</summary>
\`\`\`
${this._data.workspaceInfo};
\`\`\`
</details>
`;
}
private generateExtensionsMd(): string {
if (this._data.extensionsDisabled) {
return 'Extensions disabled';
}
const themeExclusionStr = this._data.numberOfThemeExtesions ? `\n(${this._data.numberOfThemeExtesions} theme extensions excluded)` : '';
if (!this._data.enabledNonThemeExtesions) {
return 'Extensions: none' + themeExclusionStr;
}
const tableHeader = `Extension|Author (truncated)|Version
---|---|---`;
const table = this._data.enabledNonThemeExtesions.map(e => {
return `${e.name}|${e.publisher.substr(0, 3)}|${e.version}`;
}).join('\n');
return `<details><summary>Extensions (${this._data.enabledNonThemeExtesions.length})</summary>
${tableHeader}
${table}
${themeExclusionStr}
</details>`;
}
}

View File

@@ -0,0 +1,135 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { escape } from 'vs/base/common/strings';
import { localize } from 'vs/nls';
export default (): string => `
<div id="issue-reporter">
<div id="english" class="input-group hidden">${escape(localize('completeInEnglish', "Please complete the form in English."))}</div>
<div class="section">
<div class="input-group">
<label class="inline-label" for="issue-type">${escape(localize('issueTypeLabel', "This is a"))}</label>
<select id="issue-type" class="inline-form-control">
<!-- To be dynamically filled -->
</select>
</div>
<div class="input-group" id="problem-source">
<label class="inline-label" for="issue-source">${escape(localize('issueSourceLabel', "File on"))}<span class="required-input">*</span></label>
<select id="issue-source" class="inline-form-control" required>
<!-- To be dynamically filled -->
</select>
<div id="issue-source-empty-error" class="validation-error hidden" role="alert">${escape(localize('issueSourceEmptyValidation', "An issue source is required."))}</div>
<div id="problem-source-help-text" class="instructions hidden">${escape(localize('disableExtensionsLabelText', "Try to reproduce the problem after {0}. If the problem only reproduces when extensions are active, it is likely an issue with an extension."))
.replace('{0}', `<span tabIndex=0 role="button" id="disableExtensions" class="workbenchCommand">${escape(localize('disableExtensions', "disabling all extensions and reloading the window"))}</span>`)}
</div>
<div id="extension-selection">
<label class="inline-label" for="extension-selector">${escape(localize('chooseExtension', "Extension"))} <span class="required-input">*</span></label>
<select id="extension-selector" class="inline-form-control">
<!-- To be dynamically filled -->
</select>
<div id="extension-selection-validation-error" class="validation-error hidden" role="alert">${escape(localize('extensionWithNonstandardBugsUrl', "The issue reporter is unable to create issues for this extension. Please visit {0} to report an issue."))
.replace('{0}', `<span tabIndex=0 role="button" id="extensionBugsLink" class="workbenchCommand"><!-- To be dynamically filled --></span>`)}</div>
<div id="extension-selection-validation-error-no-url" class="validation-error hidden" role="alert">
${escape(localize('extensionWithNoBugsUrl', "The issue reporter is unable to create issues for this extension, as it does not specify a URL for reporting issues. Please check the marketplace page of this extension to see if other instructions are available."))}
</div>
</div>
</div>
<div class="input-group">
<label class="inline-label" for="issue-title">${escape(localize('issueTitleLabel', "Title"))} <span class="required-input">*</span></label>
<input id="issue-title" type="text" class="inline-form-control" placeholder="${escape(localize('issueTitleRequired', "Please enter a title."))}" required>
<div id="issue-title-empty-error" class="validation-error hidden" role="alert">${escape(localize('titleEmptyValidation', "A title is required."))}</div>
<div id="issue-title-length-validation-error" class="validation-error hidden" role="alert">${escape(localize('titleLengthValidation', "The title is too long."))}</div>
<small id="similar-issues">
<!-- To be dynamically filled -->
</small>
</div>
</div>
<div class="input-group description-section">
<label for="description" id="issue-description-label">
<!-- To be dynamically filled -->
</label>
<div class="instructions" id="issue-description-subtitle">
<!-- To be dynamically filled -->
</div>
<div class="block-info-text">
<textarea name="description" id="description" placeholder="${escape(localize('details', "Please enter details."))}" required></textarea>
</div>
<div id="description-empty-error" class="validation-error hidden" role="alert">${escape(localize('descriptionEmptyValidation', "A description is required."))}</div>
</div>
<div class="system-info" id="block-container">
<div class="block block-system">
<input class="sendData" type="checkbox" id="includeSystemInfo" checked/>
<label class="caption" for="includeSystemInfo">${escape(localize({
key: 'sendSystemInfo',
comment: ['{0} is either "show" or "hide" and is a button to toggle the visibility of the system information']
}, "Include my system information ({0})")).replace('{0}', `<a href="#" class="showInfo">${escape(localize('show', "show"))}</a>`)}</label>
<div class="block-info hidden">
<!-- To be dynamically filled -->
</div>
</div>
<div class="block block-process">
<input class="sendData" type="checkbox" id="includeProcessInfo" checked/>
<label class="caption" for="includeProcessInfo">${escape(localize({
key: 'sendProcessInfo',
comment: ['{0} is either "show" or "hide" and is a button to toggle the visibility of the process info']
}, "Include my currently running processes ({0})")).replace('{0}', `<a href="#" class="showInfo">${escape(localize('show', "show"))}</a>`)}</label>
<pre class="block-info hidden">
<code>
<!-- To be dynamically filled -->
</code>
</pre>
</div>
<div class="block block-workspace">
<input class="sendData" type="checkbox" id="includeWorkspaceInfo" checked/>
<label class="caption" for="includeWorkspaceInfo">${escape(localize({
key: 'sendWorkspaceInfo',
comment: ['{0} is either "show" or "hide" and is a button to toggle the visibility of the workspace information']
}, "Include my workspace metadata ({0})")).replace('{0}', `<a href="#" class="showInfo">${escape(localize('show', "show"))}</a>`)}</label>
<pre id="systemInfo" class="block-info hidden">
<code>
<!-- To be dynamically filled -->
</code>
</pre>
</div>
<div class="block block-extensions">
<input class="sendData" type="checkbox" id="includeExtensions" checked/>
<label class="caption" for="includeExtensions">${escape(localize({
key: 'sendExtensions',
comment: ['{0} is either "show" or "hide" and is a button to toggle the visibility of the enabled extensions list']
}, "Include my enabled extensions ({0})")).replace('{0}', `<a href="#" class="showInfo">${escape(localize('show', "show"))}</a>`)}</label>
<div id="systemInfo" class="block-info hidden">
<!-- To be dynamically filled -->
</div>
</div>
<div class="block block-searchedExtensions">
<input class="sendData" type="checkbox" id="includeSearchedExtensions" checked/>
<label class="caption" for="includeSearchedExtensions">${escape(localize({
key: 'sendSearchedExtensions',
comment: ['{0} is either "show" or "hide" and is a button to toggle the visibility of the searched extensions']
}, "Send searched extensions ({0})")).replace('{0}', `<a href="#" class="showInfo">${escape(localize('show', "show"))}</a>`)}</label>
<div class="block-info hidden">
<!-- To be dynamically filled -->
</div>
</div>
<div class="block block-settingsSearchResults">
<input class="sendData" type="checkbox" id="includeSettingsSearchDetails" checked/>
<label class="caption" for="includeSettingsSearchDetails">${escape(localize({
key: 'sendSettingsSearchDetails',
comment: ['{0} is either "show" or "hide" and is a button to toggle the visibility of the search details']
}, "Send settings search details ({0})")).replace('{0}', `<a href="#" class="showInfo">${escape(localize('show', "show"))}</a>`)}</label>
<div class="block-info hidden">
<!-- To be dynamically filled -->
</div>
</div>
</div>
</div>`;

View File

@@ -0,0 +1,374 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/**
* Table
*/
table {
width: 100%;
max-width: 100%;
background-color: transparent;
border-collapse: collapse;
}
th {
vertical-align: bottom;
border-bottom: 1px solid;
padding: 5px;
text-align: inherit;
}
td {
padding: 5px;
vertical-align: top;
}
tr td:first-child {
width: 30%;
}
label {
user-select: none;
}
.block-settingsSearchResults-details {
padding-bottom: .5rem;
}
.block-settingsSearchResults-details > div {
padding: .5rem .75rem;
}
.section {
margin-bottom: .5em;
}
/**
* Forms
*/
input[type="text"], textarea {
display: block;
width: 100%;
padding: .375rem .75rem;
font-size: 1rem;
line-height: 1.5;
color: #495057;
background-color: #fff;
border: 1px solid #ced4da;
}
textarea {
overflow: auto;
resize: vertical;
}
/**
* Button
*/
.monaco-text-button {
display: block;
width: auto;
padding: 4px 10px;
align-self: flex-end;
margin-bottom: 10px;
}
select {
height: calc(2.25rem + 2px);
display: inline-block;
padding: 3px 3px;
font-size: 14px;
line-height: 1.5;
color: #495057;
background-color: #fff;
border: none;
}
* {
box-sizing: border-box;
}
textarea, input, select {
font-family: inherit;
}
html {
color: #CCCCCC;
height: 100%;
}
/* Font Families (with CJK support) */
.mac { font-family: -apple-system, BlinkMacSystemFont, sans-serif; }
.mac:lang(zh-Hans) { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", sans-serif; }
.mac:lang(zh-Hant) { font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", sans-serif; }
.mac:lang(ja) { font-family: -apple-system, BlinkMacSystemFont, "Hiragino Kaku Gothic Pro", sans-serif; }
.mac:lang(ko) { font-family: -apple-system, BlinkMacSystemFont, "Nanum Gothic", "Apple SD Gothic Neo", "AppleGothic", sans-serif; }
.windows { font-family: "Segoe WPC", "Segoe UI", sans-serif; }
.windows:lang(zh-Hans) { font-family: "Segoe WPC", "Segoe UI", "Microsoft YaHei", sans-serif; }
.windows:lang(zh-Hant) { font-family: "Segoe WPC", "Segoe UI", "Microsoft Jhenghei", sans-serif; }
.windows:lang(ja) { font-family: "Segoe WPC", "Segoe UI", "Yu Gothic UI", "Meiryo UI", sans-serif; }
.windows:lang(ko) { font-family: "Segoe WPC", "Segoe UI", "Malgun Gothic", "Dotom", sans-serif; }
/* Linux: add `system-ui` as first font and not `Ubuntu` to allow other distribution pick their standard OS font */
.linux { font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif; }
.linux:lang(zh-Hans) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans SC", "Source Han Sans CN", "Source Han Sans", sans-serif; }
.linux:lang(zh-Hant) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans TC", "Source Han Sans TW", "Source Han Sans", sans-serif; }
.linux:lang(ja) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", sans-serif; }
.linux:lang(ko) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans K", "Source Han Sans JR", "Source Han Sans", "UnDotum", "FBaekmuk Gulim", sans-serif; }
body {
margin: 0;
overflow-y: scroll;
height: 100%;
}
.hidden {
display: none;
}
.block {
font-size: 12px;
}
.block .block-info {
width: 100%;
font-size: 12px;
overflow: auto;
overflow-wrap: break-word;
margin: 5px;
padding: 10px;
}
#issue-reporter {
max-width: 85vw;
margin-left: auto;
margin-right: auto;
padding-top: 2em;
padding-bottom: 2em;
display: flex;
flex-direction: column;
height: 100%;
}
.description-section {
flex-grow: 1;
display: flex;
flex-direction: column;
flex-shrink: 0;
}
textarea {
flex-grow: 1;
min-height: 150px;
}
.block-info-text {
display: flex;
flex-grow: 1;
}
#github-submit-btn {
flex-shrink: 0;
margin-left: auto;
margin-top: 10px;
margin-bottom: 10px;
}
.two-col {
display: inline-block;
width: 49%;
}
#vscode-version {
width: 90%;
}
.input-group {
margin-bottom: 1em;
}
#extension-selection {
margin-top: 1em;
}
select, input, textarea {
border: 1px solid transparent;
margin-top: 10px;
}
#issue-reporter .validation-error {
font-size: 12px;
padding: 10px;
border-top: 0px !important;
}
input[type="checkbox"] {
width: auto;
display: inline-block;
margin-top: 0;
vertical-align: middle;
cursor: pointer;
}
input:disabled {
opacity: 0.6;
}
.list-title {
margin-top: 1em;
margin-left: 1em;
}
.instructions {
font-size: 12px;
margin-top: .5em;
}
a, .workbenchCommand {
cursor: pointer;
border: 1px solid transparent;
}
.workbenchCommand:disabled {
color: #868e96;
cursor: default
}
.block-extensions .block-info {
margin-bottom: 1.5em;
}
/* Default styles, overwritten if a theme is provided */
input, select, textarea {
background-color: #3c3c3c;
border: none;
color: #cccccc;
}
a {
color: #CCCCCC;
text-decoration: none;
}
.section .input-group .validation-error {
margin-left: 100px;
}
.section .inline-form-control, .section .inline-label {
display: inline-block;
}
.section .inline-label {
width: 95px;
}
.section .inline-form-control, .section .input-group .validation-error {
width: calc(100% - 100px);
}
#issue-type {
cursor: pointer;
}
#similar-issues {
margin-left: 15%;
display: block;
}
#problem-source-help-text {
margin-left: calc(15% + 1em);
}
@media (max-width: 950px) {
.section .inline-label {
width: 15%;
}
#problem-source-help-text {
margin-left: calc(15% + 1em);
}
.section .inline-form-control, .section .input-group .validation-error {
width: calc(85% - 5px);
}
.section .input-group .validation-error {
margin-left: calc(15% + 4px);
}
}
@media (max-width: 620px) {
.section .inline-label {
display: none !important;
}
#problem-source-help-text {
margin-left: 1em;
}
.section .inline-form-control, .section .input-group .validation-error {
width: 100%;
}
#similar-issues, .section .input-group .validation-error {
margin-left: 0;
}
}
::-webkit-scrollbar {
width: 14px;
}
::-webkit-scrollbar-thumb {
min-height: 20px;
}
::-webkit-scrollbar-corner {
display: none;
}
.issues-container {
margin-left: 1.5em;
margin-top: .5em;
max-height: 92px;
overflow-y: auto;
}
.issues-container > .issue {
padding: 4px 0;
display: flex;
}
.issues-container > .issue > .issue-link {
width: calc(100% - 82px);
overflow: hidden;
padding-top: 3px;
white-space: nowrap;
text-overflow: ellipsis;
}
.issues-container > .issue > .issue-state .codicon {
width: 16px;
}
.issues-container > .issue > .issue-state {
width: 77px;
padding: 3px 6px;
margin-right: 5px;
color: #CCCCCC;
background-color: #3c3c3c;
border-radius: .25rem;
}
.issues-container > .issue .label {
margin-left: 5px;
width: 44px;
text-overflow: ellipsis;
overflow: hidden;
}

View File

@@ -0,0 +1,222 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { IssueReporterModel } from 'vs/code/electron-sandbox/issue/issueReporterModel';
import { normalizeGitHubUrl } from 'vs/platform/issue/common/issueReporterUtil';
import { IssueType } from 'vs/platform/issue/common/issue';
suite('IssueReporter', () => {
test('sets defaults to include all data', () => {
const issueReporterModel = new IssueReporterModel();
assert.deepEqual(issueReporterModel.getData(), {
allExtensions: [],
includeSystemInfo: true,
includeWorkspaceInfo: true,
includeProcessInfo: true,
includeExtensions: true,
includeSearchedExtensions: true,
includeSettingsSearchDetails: true,
issueType: 0
});
});
test('serializes model skeleton when no data is provided', () => {
const issueReporterModel = new IssueReporterModel({});
assert.equal(issueReporterModel.serialize(),
`
Issue Type: <b>Bug</b>
undefined
VS Code version: undefined
OS version: undefined
Extensions: none
<!-- generated by issue reporter -->`);
});
test('serializes GPU information when data is provided', () => {
const issueReporterModel = new IssueReporterModel({
issueType: 0,
systemInfo: {
os: 'Darwin',
cpus: 'Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz (8 x 2800)',
memory: '16.00GB',
vmHint: '0%',
processArgs: '',
screenReader: 'no',
remoteData: [],
gpuStatus: {
'2d_canvas': 'enabled',
'checker_imaging': 'disabled_off'
}
}
});
assert.equal(issueReporterModel.serialize(),
`
Issue Type: <b>Bug</b>
undefined
VS Code version: undefined
OS version: undefined
<details>
<summary>System Info</summary>
|Item|Value|
|---|---|
|CPUs|Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz (8 x 2800)|
|GPU Status|2d_canvas: enabled<br>checker_imaging: disabled_off|
|Load (avg)|undefined|
|Memory (System)|16.00GB|
|Process Argv||
|Screen Reader|no|
|VM|0%|
</details>Extensions: none
<!-- generated by issue reporter -->`);
});
test('serializes Linux environment information when data is provided', () => {
const issueReporterModel = new IssueReporterModel({
issueType: 0,
systemInfo: {
os: 'Darwin',
cpus: 'Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz (8 x 2800)',
memory: '16.00GB',
vmHint: '0%',
processArgs: '',
screenReader: 'no',
remoteData: [],
gpuStatus: {},
linuxEnv: {
desktopSession: 'ubuntu',
xdgCurrentDesktop: 'ubuntu',
xdgSessionDesktop: 'ubuntu:GNOME',
xdgSessionType: 'x11'
}
}
});
assert.equal(issueReporterModel.serialize(),
`
Issue Type: <b>Bug</b>
undefined
VS Code version: undefined
OS version: undefined
<details>
<summary>System Info</summary>
|Item|Value|
|---|---|
|CPUs|Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz (8 x 2800)|
|GPU Status||
|Load (avg)|undefined|
|Memory (System)|16.00GB|
|Process Argv||
|Screen Reader|no|
|VM|0%|
|DESKTOP_SESSION|ubuntu|
|XDG_CURRENT_DESKTOP|ubuntu|
|XDG_SESSION_DESKTOP|ubuntu:GNOME|
|XDG_SESSION_TYPE|x11|
</details>Extensions: none
<!-- generated by issue reporter -->`);
});
test('serializes remote information when data is provided', () => {
const issueReporterModel = new IssueReporterModel({
issueType: 0,
systemInfo: {
os: 'Darwin',
cpus: 'Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz (8 x 2800)',
memory: '16.00GB',
vmHint: '0%',
processArgs: '',
screenReader: 'no',
gpuStatus: {
'2d_canvas': 'enabled',
'checker_imaging': 'disabled_off'
},
remoteData: [
{
hostName: 'SSH: Pineapple',
machineInfo: {
os: 'Linux x64 4.18.0',
cpus: 'Intel(R) Xeon(R) CPU E5-2673 v4 @ 2.30GHz (2 x 2294)',
memory: '8GB',
vmHint: '100%'
}
}
]
}
});
assert.equal(issueReporterModel.serialize(),
`
Issue Type: <b>Bug</b>
undefined
VS Code version: undefined
OS version: undefined
Remote OS version: Linux x64 4.18.0
<details>
<summary>System Info</summary>
|Item|Value|
|---|---|
|CPUs|Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz (8 x 2800)|
|GPU Status|2d_canvas: enabled<br>checker_imaging: disabled_off|
|Load (avg)|undefined|
|Memory (System)|16.00GB|
|Process Argv||
|Screen Reader|no|
|VM|0%|
|Item|Value|
|---|---|
|Remote|SSH: Pineapple|
|OS|Linux x64 4.18.0|
|CPUs|Intel(R) Xeon(R) CPU E5-2673 v4 @ 2.30GHz (2 x 2294)|
|Memory (System)|8GB|
|VM|100%|
</details>Extensions: none
<!-- generated by issue reporter -->`);
});
test('should normalize GitHub urls', () => {
[
'https://github.com/repo',
'https://github.com/repo/',
'https://github.com/repo.git',
'https://github.com/repo/issues',
'https://github.com/repo/issues/',
'https://github.com/repo/issues/new',
'https://github.com/repo/issues/new/'
].forEach(url => {
assert.equal('https://github.com/repo', normalizeGitHubUrl(url));
});
});
test('should have support for filing on extensions for bugs, performance issues, and feature requests', () => {
[
IssueType.Bug,
IssueType.FeatureRequest,
IssueType.PerformanceIssue
].forEach(type => {
const issueReporterModel = new IssueReporterModel({
issueType: type,
fileOnExtension: true
});
assert.equal(issueReporterModel.fileOnExtension(), true);
});
});
});

View File

@@ -0,0 +1,107 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
html {
font-size: 13px;
}
/* Font Families (with CJK support) */
.mac { font-family: -apple-system, BlinkMacSystemFont, sans-serif; }
.mac:lang(zh-Hans) { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", sans-serif; }
.mac:lang(zh-Hant) { font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", sans-serif; }
.mac:lang(ja) { font-family: -apple-system, BlinkMacSystemFont, "Hiragino Kaku Gothic Pro", sans-serif; }
.mac:lang(ko) { font-family: -apple-system, BlinkMacSystemFont, "Nanum Gothic", "Apple SD Gothic Neo", "AppleGothic", sans-serif; }
.windows { font-family: "Segoe WPC", "Segoe UI", sans-serif; }
.windows:lang(zh-Hans) { font-family: "Segoe WPC", "Segoe UI", "Microsoft YaHei", sans-serif; }
.windows:lang(zh-Hant) { font-family: "Segoe WPC", "Segoe UI", "Microsoft Jhenghei", sans-serif; }
.windows:lang(ja) { font-family: "Segoe WPC", "Segoe UI", "Yu Gothic UI", "Meiryo UI", sans-serif; }
.windows:lang(ko) { font-family: "Segoe WPC", "Segoe UI", "Malgun Gothic", "Dotom", sans-serif; }
/* Linux: add `system-ui` as first font and not `Ubuntu` to allow other distribution pick their standard OS font */
.linux { font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif; }
.linux:lang(zh-Hans) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans SC", "Source Han Sans CN", "Source Han Sans", sans-serif; }
.linux:lang(zh-Hant) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans TC", "Source Han Sans TW", "Source Han Sans", sans-serif; }
.linux:lang(ja) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", sans-serif; }
.linux:lang(ko) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans K", "Source Han Sans JR", "Source Han Sans", "UnDotum", "FBaekmuk Gulim", sans-serif; }
body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
user-select: none;
color: #cccccc;
}
.cpu {
width: 45px;
}
.pid {
width: 50px
}
.memory {
width: 90px;
}
.process-item {
line-height: 22px;
}
table {
border-collapse: collapse;
width: 100%;
table-layout: fixed;
}
th[scope='col'] {
vertical-align: bottom;
border-bottom: 1px solid #cccccc;
padding: .5rem;
border-top: 1px solid #cccccc;
cursor: default;
}
td {
padding: .25rem;
vertical-align: top;
cursor: default;
}
.centered {
text-align: center;
}
.nameLabel{
text-align: left;
}
.data {
white-space: pre;
padding-left: .5rem;
font-weight: normal;
text-align: left;
height: 22px;
}
.error {
padding-left: 20px;
white-space: nowrap;
}
tbody > tr:hover {
background-color: #2A2D2E;
}
.hidden {
display: none;
}
.header {
display: flex;
}

View File

@@ -0,0 +1,19 @@
<!-- Copyright (C) Microsoft Corporation. All rights reserved. -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data:; media-src 'none'; child-src 'self'; object-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; font-src 'self' https:;">
</head>
<body aria-label="">
<table id="process-list"></table>
</body>
<!-- Init Bootstrap Helpers -->
<script src="../../../../bootstrap.js"></script>
<script src="../../../../vs/loader.js"></script>
<script src="../../../../bootstrap-window.js"></script>
<!-- Startup via processExplorer.js -->
<script src="processExplorer.js"></script>
</html>

View File

@@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
//@ts-check
'use strict';
(function () {
const bootstrapWindow = bootstrapWindowLib();
// Load process explorer into window
bootstrapWindow.load(['vs/code/electron-sandbox/processExplorer/processExplorerMain'], function (processExplorer, configuration) {
processExplorer.startup(configuration.windowId, configuration.data);
}, { forceEnableDeveloperKeybindings: true });
//#region Globals
/**
* @returns {{ load: (modules: string[], resultCallback: (result, configuration: object) => any, options?: object) => unknown }}
*/
function bootstrapWindowLib() {
// @ts-ignore (defined in bootstrap-window.js)
return window.MonacoBootstrapWindow;
}
//#endregion
}());

View File

@@ -0,0 +1,447 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/processExplorer';
import 'vs/base/browser/ui/codicons/codiconStyles'; // make sure codicon css is loaded
import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
import { NativeHostService } from 'vs/platform/native/electron-sandbox/nativeHostService';
import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
import { localize } from 'vs/nls';
import { ProcessExplorerStyles, ProcessExplorerData } from 'vs/platform/issue/common/issue';
import { applyZoom, zoomIn, zoomOut } from 'vs/platform/windows/electron-sandbox/window';
import { IContextMenuItem } from 'vs/base/parts/contextmenu/common/contextmenu';
import { popup } from 'vs/base/parts/contextmenu/electron-sandbox/contextmenu';
import { ProcessItem } from 'vs/base/common/processes';
import { addDisposableListener, $ } from 'vs/base/browser/dom';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { isRemoteDiagnosticError, IRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
import { MainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
import { CodiconLabel } from 'vs/base/browser/ui/codicons/codiconLabel';
const DEBUG_FLAGS_PATTERN = /\s--(inspect|debug)(-brk|port)?=(\d+)?/;
const DEBUG_PORT_PATTERN = /\s--(inspect|debug)-port=(\d+)/;
interface FormattedProcessItem {
cpu: number;
memory: number;
pid: string;
name: string;
formattedName: string;
cmd: string;
}
class ProcessExplorer {
private lastRequestTime: number;
private collapsedStateCache: Map<string, boolean> = new Map<string, boolean>();
private mapPidToWindowTitle = new Map<number, string>();
private listeners = new DisposableStore();
private nativeHostService: INativeHostService;
constructor(windowId: number, private data: ProcessExplorerData) {
const mainProcessService = new MainProcessService(windowId);
this.nativeHostService = new NativeHostService(windowId, mainProcessService) as INativeHostService;
this.applyStyles(data.styles);
// Map window process pids to titles, annotate process names with this when rendering to distinguish between them
ipcRenderer.on('vscode:windowsInfoResponse', (event: unknown, windows: any[]) => {
this.mapPidToWindowTitle = new Map<number, string>();
windows.forEach(window => this.mapPidToWindowTitle.set(window.pid, window.title));
});
ipcRenderer.on('vscode:listProcessesResponse', (event: unknown, processRoots: [{ name: string, rootProcess: ProcessItem | IRemoteDiagnosticError }]) => {
this.updateProcessInfo(processRoots);
this.requestProcessList(0);
});
this.lastRequestTime = Date.now();
ipcRenderer.send('vscode:windowsInfoRequest');
ipcRenderer.send('vscode:listProcesses');
}
private getProcessList(rootProcess: ProcessItem, isLocal: boolean, totalMem: number): FormattedProcessItem[] {
const processes: FormattedProcessItem[] = [];
if (rootProcess) {
this.getProcessItem(processes, rootProcess, 0, isLocal, totalMem);
}
return processes;
}
private getProcessItem(processes: FormattedProcessItem[], item: ProcessItem, indent: number, isLocal: boolean, totalMem: number): void {
const isRoot = (indent === 0);
const MB = 1024 * 1024;
let name = item.name;
if (isRoot) {
name = isLocal ? `${this.data.applicationName} main` : 'remote agent';
}
if (name === 'window') {
const windowTitle = this.mapPidToWindowTitle.get(item.pid);
name = windowTitle !== undefined ? `${name} (${this.mapPidToWindowTitle.get(item.pid)})` : name;
}
// Format name with indent
const formattedName = isRoot ? name : `${' '.repeat(indent)} ${name}`;
const memory = this.data.platform === 'win32' ? item.mem : (totalMem * (item.mem / 100));
processes.push({
cpu: item.load,
memory: (memory / MB),
pid: item.pid.toFixed(0),
name,
formattedName,
cmd: item.cmd
});
// Recurse into children if any
if (Array.isArray(item.children)) {
item.children.forEach(child => {
if (child) {
this.getProcessItem(processes, child, indent + 1, isLocal, totalMem);
}
});
}
}
private isDebuggable(cmd: string): boolean {
const matches = DEBUG_FLAGS_PATTERN.exec(cmd);
return (matches && matches.length >= 2) || cmd.indexOf('node ') >= 0 || cmd.indexOf('node.exe') >= 0;
}
private attachTo(item: FormattedProcessItem) {
const config: any = {
type: 'node',
request: 'attach',
name: `process ${item.pid}`
};
let matches = DEBUG_FLAGS_PATTERN.exec(item.cmd);
if (matches && matches.length >= 2) {
// attach via port
if (matches.length === 4 && matches[3]) {
config.port = parseInt(matches[3]);
}
config.protocol = matches[1] === 'debug' ? 'legacy' : 'inspector';
} else {
// no port -> try to attach via pid (send SIGUSR1)
config.processId = String(item.pid);
}
// a debug-port=n or inspect-port=n overrides the port
matches = DEBUG_PORT_PATTERN.exec(item.cmd);
if (matches && matches.length === 3) {
// override port
config.port = parseInt(matches[2]);
}
ipcRenderer.send('vscode:workbenchCommand', { id: 'debug.startFromConfig', from: 'processExplorer', args: [config] });
}
private getProcessIdWithHighestProperty(processList: any[], propertyName: string) {
let max = 0;
let maxProcessId;
processList.forEach(process => {
if (process[propertyName] > max) {
max = process[propertyName];
maxProcessId = process.pid;
}
});
return maxProcessId;
}
private updateSectionCollapsedState(shouldExpand: boolean, body: HTMLElement, twistie: CodiconLabel, sectionName: string) {
if (shouldExpand) {
body.classList.remove('hidden');
this.collapsedStateCache.set(sectionName, false);
twistie.text = '$(chevron-down)';
} else {
body.classList.add('hidden');
this.collapsedStateCache.set(sectionName, true);
twistie.text = '$(chevron-right)';
}
}
private renderProcessFetchError(sectionName: string, errorMessage: string) {
const container = document.getElementById('process-list');
if (!container) {
return;
}
const body = document.createElement('tbody');
this.renderProcessGroupHeader(sectionName, body, container);
const errorRow = document.createElement('tr');
const data = document.createElement('td');
data.textContent = errorMessage;
data.className = 'error';
data.colSpan = 4;
errorRow.appendChild(data);
body.appendChild(errorRow);
container.appendChild(body);
}
private renderProcessGroupHeader(sectionName: string, body: HTMLElement, container: HTMLElement) {
const headerRow = document.createElement('tr');
const headerData = document.createElement('td');
headerData.colSpan = 4;
headerRow.appendChild(headerData);
const headerContainer = document.createElement('div');
headerContainer.className = 'header';
headerData.appendChild(headerContainer);
const twistieContainer = document.createElement('div');
const twistieCodicon = new CodiconLabel(twistieContainer);
this.updateSectionCollapsedState(!this.collapsedStateCache.get(sectionName), body, twistieCodicon, sectionName);
headerContainer.appendChild(twistieContainer);
const headerLabel = document.createElement('span');
headerLabel.textContent = sectionName;
headerContainer.appendChild(headerLabel);
this.listeners.add(addDisposableListener(headerData, 'click', (e) => {
const isHidden = body.classList.contains('hidden');
this.updateSectionCollapsedState(isHidden, body, twistieCodicon, sectionName);
}));
container.appendChild(headerRow);
}
private renderTableSection(sectionName: string, processList: FormattedProcessItem[], renderManySections: boolean, sectionIsLocal: boolean): void {
const container = document.getElementById('process-list');
if (!container) {
return;
}
const highestCPUProcess = this.getProcessIdWithHighestProperty(processList, 'cpu');
const highestMemoryProcess = this.getProcessIdWithHighestProperty(processList, 'memory');
const body = document.createElement('tbody');
if (renderManySections) {
this.renderProcessGroupHeader(sectionName, body, container);
}
processList.forEach(p => {
const row = document.createElement('tr');
row.id = p.pid.toString();
const cpu = document.createElement('td');
p.pid === highestCPUProcess
? cpu.classList.add('centered', 'highest')
: cpu.classList.add('centered');
cpu.textContent = p.cpu.toFixed(0);
const memory = document.createElement('td');
p.pid === highestMemoryProcess
? memory.classList.add('centered', 'highest')
: memory.classList.add('centered');
memory.textContent = p.memory.toFixed(0);
const pid = document.createElement('td');
pid.classList.add('centered');
pid.textContent = p.pid;
const name = document.createElement('th');
name.scope = 'row';
name.classList.add('data');
name.title = p.cmd;
name.textContent = p.formattedName;
row.append(cpu, memory, pid, name);
this.listeners.add(addDisposableListener(row, 'contextmenu', (e) => {
this.showContextMenu(e, p, sectionIsLocal);
}));
body.appendChild(row);
});
container.appendChild(body);
}
private async updateProcessInfo(processLists: [{ name: string, rootProcess: ProcessItem | IRemoteDiagnosticError }]): Promise<void> {
const container = document.getElementById('process-list');
if (!container) {
return;
}
container.innerText = '';
this.listeners.clear();
const tableHead = $('thead', undefined);
const row = $('tr');
tableHead.append(row);
row.append($('th.cpu', { scope: 'col' }, localize('cpu', "CPU %")));
row.append($('th.memory', { scope: 'col' }, localize('memory', "Memory (MB)")));
row.append($('th.pid', { scope: 'col' }, localize('pid', "PID")));
row.append($('th.nameLabel', { scope: 'col' }, localize('name', "Name")));
container.append(tableHead);
const hasMultipleMachines = Object.keys(processLists).length > 1;
const { totalmem } = await this.nativeHostService.getOSStatistics();
processLists.forEach((remote, i) => {
const isLocal = i === 0;
if (isRemoteDiagnosticError(remote.rootProcess)) {
this.renderProcessFetchError(remote.name, remote.rootProcess.errorMessage);
} else {
this.renderTableSection(remote.name, this.getProcessList(remote.rootProcess, isLocal, totalmem), hasMultipleMachines, isLocal);
}
});
}
private applyStyles(styles: ProcessExplorerStyles): void {
const styleTag = document.createElement('style');
const content: string[] = [];
if (styles.hoverBackground) {
content.push(`tbody > tr:hover, table > tr:hover { background-color: ${styles.hoverBackground}; }`);
}
if (styles.hoverForeground) {
content.push(`tbody > tr:hover, table > tr:hover { color: ${styles.hoverForeground}; }`);
}
if (styles.highlightForeground) {
content.push(`.highest { color: ${styles.highlightForeground}; }`);
}
styleTag.textContent = content.join('\n');
if (document.head) {
document.head.appendChild(styleTag);
}
if (styles.color) {
document.body.style.color = styles.color;
}
}
private showContextMenu(e: MouseEvent, item: FormattedProcessItem, isLocal: boolean) {
e.preventDefault();
const items: IContextMenuItem[] = [];
const pid = Number(item.pid);
if (isLocal) {
items.push({
label: localize('killProcess', "Kill Process"),
click: () => {
this.nativeHostService.killProcess(pid, 'SIGTERM');
}
});
items.push({
label: localize('forceKillProcess', "Force Kill Process"),
click: () => {
this.nativeHostService.killProcess(pid, 'SIGKILL');
}
});
items.push({
type: 'separator'
});
}
items.push({
label: localize('copy', "Copy"),
click: () => {
const row = document.getElementById(pid.toString());
if (row) {
this.nativeHostService.writeClipboardText(row.innerText);
}
}
});
items.push({
label: localize('copyAll', "Copy All"),
click: () => {
const processList = document.getElementById('process-list');
if (processList) {
this.nativeHostService.writeClipboardText(processList.innerText);
}
}
});
if (item && isLocal && this.isDebuggable(item.cmd)) {
items.push({
type: 'separator'
});
items.push({
label: localize('debug', "Debug"),
click: () => {
this.attachTo(item);
}
});
}
popup(items);
}
private requestProcessList(totalWaitTime: number): void {
setTimeout(() => {
const nextRequestTime = Date.now();
const waited = totalWaitTime + nextRequestTime - this.lastRequestTime;
this.lastRequestTime = nextRequestTime;
// Wait at least a second between requests.
if (waited > 1000) {
ipcRenderer.send('vscode:windowsInfoRequest');
ipcRenderer.send('vscode:listProcesses');
} else {
this.requestProcessList(waited);
}
}, 200);
}
public dispose() {
this.listeners.dispose();
}
}
export function startup(windowId: number, data: ProcessExplorerData): void {
const platformClass = data.platform === 'win32' ? 'windows' : data.platform === 'linux' ? 'linux' : 'mac';
document.body.classList.add(platformClass); // used by our fonts
applyZoom(data.zoomLevel);
const processExplorer = new ProcessExplorer(windowId, data);
document.onkeydown = (e: KeyboardEvent) => {
const cmdOrCtrlKey = data.platform === 'darwin' ? e.metaKey : e.ctrlKey;
// Cmd/Ctrl + w closes issue window
if (cmdOrCtrlKey && e.keyCode === 87) {
e.stopPropagation();
e.preventDefault();
processExplorer.dispose();
ipcRenderer.send('vscode:closeProcessExplorer');
}
// Cmd/Ctrl + zooms in
if (cmdOrCtrlKey && e.keyCode === 187) {
zoomIn();
}
// Cmd/Ctrl - zooms out
if (cmdOrCtrlKey && e.keyCode === 189) {
zoomOut();
}
};
}

View File

@@ -0,0 +1,83 @@
<!-- Copyright (C) Microsoft Corporation. All rights reserved. -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Security-Policy"
content="default-src 'none'; img-src 'self' https: data:; media-src 'none'; child-src 'self'; object-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; font-src 'self' https:;">
<style>
html,
body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
overflow: hidden;
user-select: none;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", system-ui, "Ubuntu", "Droid Sans", sans-serif;
font-size: 10pt;
background-color: #F3F3F3;
}
#main {
box-sizing: border-box;
padding: 10px;
}
h1 {
margin: 0;
padding: 10px 0;
font-size: 16px;
background-color: #555;
color: #f0f0f0;
text-align: center;
}
#form {
margin-top: 10px;
}
#username,
#password {
padding: 6px 10px;
font-size: 12px;
box-sizing: border-box;
width: 100%;
}
#buttons {
text-align: center;
}
p {
margin: 6px 0;
}
input {
font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", system-ui, "Ubuntu", "Droid Sans", sans-serif !important;
}
</style>
</head>
<body>
<h1 id="title"></h1>
<section id="main">
<p id="message"></p>
<form id="form">
<p><input type="text" id="username" placeholder="Username" required /></p>
<p><input type="password" id="password" placeholder="Password" required /></p>
<p id="buttons">
<input id="ok" type="submit" value="OK" />
<input id="cancel" type="button" value="Cancel" />
</p>
</form>
</section>
</body>
<script src="auth.js"></script>
</html>

View File

@@ -0,0 +1,48 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
const { ipcRenderer } = window.vscode;
function promptForCredentials(data) {
return new Promise((c, e) => {
const $title = document.getElementById('title');
const $username = document.getElementById('username');
const $password = document.getElementById('password');
const $form = document.getElementById('form');
const $cancel = document.getElementById('cancel');
const $message = document.getElementById('message');
function submit() {
c({ username: $username.value, password: $password.value });
return false;
}
function cancel() {
c({ username: '', password: '' });
return false;
}
$form.addEventListener('submit', submit);
$cancel.addEventListener('click', cancel);
document.body.addEventListener('keydown', function (e) {
switch (e.keyCode) {
case 27: e.preventDefault(); e.stopPropagation(); return cancel();
case 13: e.preventDefault(); e.stopPropagation(); return submit();
}
});
$title.textContent = data.title;
$message.textContent = data.message;
$username.focus();
});
}
ipcRenderer.on('vscode:openProxyAuthDialog', async (event, data) => {
const response = await promptForCredentials(data);
ipcRenderer.send('vscode:proxyAuthResponse', response);
});

View File

@@ -0,0 +1,18 @@
<!-- Copyright (C) Microsoft Corporation. All rights reserved. -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data: blob: vscode-remote-resource:; media-src 'none'; frame-src 'self' vscode-webview: https://*.vscode-webview-test.com; object-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; font-src 'self' https: vscode-remote-resource:;">
</head>
<body aria-label="">
</body>
<!-- Init Bootstrap Helpers -->
<script src="../../../../bootstrap.js"></script>
<script src="../../../../vs/loader.js"></script>
<script src="../../../../bootstrap-window.js"></script>
<!-- Startup via workbench.js -->
<script src="workbench.js"></script>
</html>

View File

@@ -0,0 +1,87 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/// <reference path="../../../../typings/require.d.ts" />
//@ts-check
'use strict';
(function () {
// Add a perf entry right from the top
const perf = perfLib();
perf.mark('renderer/started');
// Load environment in parallel to workbench loading to avoid waterfall
const bootstrapWindow = bootstrapWindowLib();
const whenEnvResolved = bootstrapWindow.globals().process.whenEnvResolved();
// Load workbench main JS, CSS and NLS all in parallel. This is an
// optimization to prevent a waterfall of loading to happen, because
// we know for a fact that workbench.desktop.sandbox.main will depend on
// the related CSS and NLS counterparts.
bootstrapWindow.load([
'vs/workbench/workbench.desktop.sandbox.main',
'vs/nls!vs/workbench/workbench.desktop.main',
'vs/css!vs/workbench/workbench.desktop.main'
],
async function (workbench, configuration) {
// Mark start of workbench
perf.mark('didLoadWorkbenchMain');
performance.mark('workbench-start');
// Wait for process environment being fully resolved
await whenEnvResolved;
perf.mark('main/startup');
// @ts-ignore
return require('vs/workbench/electron-sandbox/desktop.main').main(configuration);
},
{
removeDeveloperKeybindingsAfterLoad: true,
canModifyDOM: function (windowConfig) {
// TODO@sandbox part-splash is non-sandboxed only
},
beforeLoaderConfig: function (windowConfig, loaderConfig) {
loaderConfig.recordStats = true;
},
beforeRequire: function () {
perf.mark('willLoadWorkbenchMain');
}
}
);
//region Helpers
function perfLib() {
globalThis.MonacoPerformanceMarks = globalThis.MonacoPerformanceMarks || [];
return {
/**
* @param {string} name
*/
mark(name) {
globalThis.MonacoPerformanceMarks.push(name, Date.now());
}
};
}
/**
* @returns {{
* load: (modules: string[], resultCallback: (result, configuration: object) => any, options: object) => unknown,
* globals: () => typeof import('../../../base/parts/sandbox/electron-sandbox/globals')
* }}
*/
function bootstrapWindowLib() {
// @ts-ignore (defined in bootstrap-window.js)
return window.MonacoBootstrapWindow;
}
//#endregion
}());