提交 8f9f4542 编写于 作者: B Benjamin Pasero

sandbox - avoid direct use of node.js OS module

上级 2c674e39
......@@ -10,8 +10,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
import { ILogService } from 'vs/platform/log/common/log';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { onUnexpectedError } from 'vs/base/common/errors';
import * as os from 'os';
import { join } from 'vs/base/common/path';
import { joinPath } from 'vs/base/common/resources';
import { writeFile } from 'vs/base/node/pfs';
import { IExtensionHostProfileService } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
......@@ -20,8 +19,10 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsInput';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { createSlowExtensionAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions';
import { createSlowExtensionAction } from 'vs/workbench/contrib/extensions/electron-sandbox/extensionsSlowActions';
import { ExtensionHostProfiler } from 'vs/workbench/services/extensions/electron-browser/extensionHostProfiler';
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
export class ExtensionsAutoProfiler extends Disposable implements IWorkbenchContribution {
......@@ -36,6 +37,7 @@ export class ExtensionsAutoProfiler extends Disposable implements IWorkbenchCont
@INotificationService private readonly _notificationService: INotificationService,
@IEditorService private readonly _editorService: IEditorService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IWorkbenchEnvironmentService private readonly _environmentServie: INativeWorkbenchEnvironmentService
) {
super();
this._register(_extensionService.onDidChangeResponsiveChange(this._onDidChangeResponsiveChange, this));
......@@ -138,7 +140,7 @@ export class ExtensionsAutoProfiler extends Disposable implements IWorkbenchCont
// print message to log
const path = join(os.tmpdir(), `exthost-${Math.random().toString(16).slice(2, 8)}.cpuprofile`);
const path = joinPath(this._environmentServie.tmpDir, `exthost-${Math.random().toString(16).slice(2, 8)}.cpuprofile`).fsPath;
await writeFile(path, JSON.stringify(profile.data));
this._logService.warn(`UNRESPONSIVE extension host, '${top.id}' took ${top!.percentage}% of ${duration / 1e3}ms, saved PROFILE here: '${path}'`, data);
......
......@@ -5,7 +5,6 @@
import 'vs/css!./media/runtimeExtensionsEditor';
import * as nls from 'vs/nls';
import * as os from 'os';
import { IProductService } from 'vs/platform/product/common/productService';
import { Action, IAction, Separator } from 'vs/base/common/actions';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
......@@ -25,7 +24,6 @@ import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService
import { EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
import { writeFile } from 'vs/base/node/pfs';
import { memoize } from 'vs/base/common/decorators';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { Event } from 'vs/base/common/event';
......@@ -40,13 +38,15 @@ import { ILabelService } from 'vs/platform/label/common/label';
import { renderCodicons } from 'vs/base/browser/codicons';
import { ExtensionIdentifier, ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { Schemas } from 'vs/base/common/network';
import { SlowExtensionAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions';
import { SlowExtensionAction } from 'vs/workbench/contrib/extensions/electron-sandbox/extensionsSlowActions';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { URI } from 'vs/base/common/uri';
import { editorBackground } from 'vs/platform/theme/common/colorRegistry';
import { domEvent } from 'vs/base/browser/event';
import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import { IFileService } from 'vs/platform/files/common/files';
import { VSBuffer } from 'vs/base/common/buffer';
export const IExtensionHostProfileService = createDecorator<IExtensionHostProfileService>('extensionHostProfileService');
export const CONTEXT_PROFILE_SESSION_STATE = new RawContextKey<string>('profileSessionState', 'none');
......@@ -126,7 +126,8 @@ export class RuntimeExtensionsEditor extends EditorPane {
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService,
@IOpenerService private readonly _openerService: IOpenerService,
@IClipboardService private readonly _clipboardService: IClipboardService,
@IProductService private readonly _productService: IProductService
@IProductService private readonly _productService: IProductService,
@IElectronService private readonly _electronService: IElectronService
) {
super(RuntimeExtensionsEditor.ID, telemetryService, themeService, storageService);
......@@ -352,7 +353,7 @@ export class RuntimeExtensionsEditor extends EditorPane {
data.actionbar.push(this._instantiationService.createInstance(SlowExtensionAction, element.description, element.unresponsiveProfile), { icon: true, label: true });
}
if (isNonEmptyArray(element.status.runtimeErrors)) {
data.actionbar.push(new ReportExtensionIssueAction(element, this._openerService, this._clipboardService, this._productService), { icon: true, label: true });
data.actionbar.push(new ReportExtensionIssueAction(element, this._openerService, this._clipboardService, this._productService, this._electronService), { icon: true, label: true });
}
let title: string;
......@@ -467,7 +468,7 @@ export class RuntimeExtensionsEditor extends EditorPane {
const actions: IAction[] = [];
actions.push(new ReportExtensionIssueAction(e.element, this._openerService, this._clipboardService, this._productService));
actions.push(new ReportExtensionIssueAction(e.element, this._openerService, this._clipboardService, this._productService, this._electronService));
actions.push(new Separator());
actions.push(new Action('runtimeExtensionsEditor.action.disableWorkspace', nls.localize('disable workspace', "Disable (Workspace)"), undefined, true, () => this._extensionsWorkbenchService.setEnablement(e.element!.marketplaceInfo, EnablementState.DisabledWorkspace)));
......@@ -522,10 +523,10 @@ export class ReportExtensionIssueAction extends Action {
private static readonly _id = 'workbench.extensions.action.reportExtensionIssue';
private static readonly _label = nls.localize('reportExtensionIssue', "Report Issue");
private readonly _url: string;
private _url: string | undefined;
constructor(
extension: {
private extension: {
description: IExtensionDescription;
marketplaceInfo: IExtension;
status?: IExtensionsStatus;
......@@ -533,26 +534,28 @@ export class ReportExtensionIssueAction extends Action {
},
@IOpenerService private readonly openerService: IOpenerService,
@IClipboardService private readonly clipboardService: IClipboardService,
@IProductService private readonly productService: IProductService
@IProductService private readonly productService: IProductService,
@IElectronService private readonly electronService: IElectronService
) {
super(ReportExtensionIssueAction._id, ReportExtensionIssueAction._label, 'extension-action report-issue');
this.enabled = extension.marketplaceInfo
&& extension.marketplaceInfo.type === ExtensionType.User
&& !!extension.description.repository && !!extension.description.repository.url;
this._url = this._generateNewIssueUrl(extension);
}
async run(): Promise<void> {
if (!this._url) {
this._url = await this._generateNewIssueUrl(this.extension);
}
this.openerService.open(URI.parse(this._url));
}
private _generateNewIssueUrl(extension: {
private async _generateNewIssueUrl(extension: {
description: IExtensionDescription;
marketplaceInfo: IExtension;
status?: IExtensionsStatus;
unresponsiveProfile?: IExtensionHostProfile
}): string {
}): Promise<string> {
let baseUrl = extension.marketplaceInfo && extension.marketplaceInfo.type === ExtensionType.User && extension.description.repository ? extension.description.repository.url : undefined;
if (!!baseUrl) {
baseUrl = `${baseUrl.indexOf('.git') !== -1 ? baseUrl.substr(0, baseUrl.length - 4) : baseUrl}/issues/new/`;
......@@ -565,7 +568,8 @@ export class ReportExtensionIssueAction extends Action {
let message = ':warning: We have written the needed data into your clipboard. Please paste! :warning:';
this.clipboardService.writeText('```json \n' + JSON.stringify(extension.status, null, '\t') + '\n```');
const osVersion = `${os.type()} ${os.arch()} ${os.release()}`;
const os = await this.electronService.getOSProperties();
const osVersion = `${os.type} ${os.arch} ${os.release}`;
const queryStringPrefix = baseUrl.indexOf('?') === -1 ? '?' : '&';
const body = encodeURIComponent(
`- Issue Type: \`${reason}\`
......@@ -665,6 +669,7 @@ export class SaveExtensionHostProfileAction extends Action {
@IElectronService private readonly _electronService: IElectronService,
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService,
@IExtensionHostProfileService private readonly _extensionHostProfileService: IExtensionHostProfileService,
@IFileService private readonly _fileService: IFileService
) {
super(id, label, undefined, false);
this._extensionHostProfileService.onDidChangeLastProfile(() => {
......@@ -709,7 +714,7 @@ export class SaveExtensionHostProfileAction extends Action {
savePath = savePath + '.txt';
}
return writeFile(savePath, JSON.stringify(profileInfo ? profileInfo.data : {}, null, '\t'));
return this._fileService.writeFile(URI.file(savePath), VSBuffer.fromString(JSON.stringify(profileInfo ? profileInfo.data : {}, null, '\t')));
}
}
......
......@@ -3,7 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as os from 'os';
import { IProductService } from 'vs/platform/product/common/productService';
import { Action } from 'vs/base/common/actions';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
......@@ -13,11 +12,14 @@ import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiati
import { localize } from 'vs/nls';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IRequestService, asText } from 'vs/platform/request/common/request';
import { join } from 'vs/base/common/path';
import { joinPath } from 'vs/base/common/resources';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import Severity from 'vs/base/common/severity';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
abstract class RepoInfo {
abstract get base(): string;
......@@ -119,7 +121,9 @@ class ReportExtensionSlowAction extends Action {
readonly profile: IExtensionHostProfile,
@IDialogService private readonly _dialogService: IDialogService,
@IOpenerService private readonly _openerService: IOpenerService,
@IProductService private readonly _productService: IProductService
@IProductService private readonly _productService: IProductService,
@IElectronService private readonly _electronService: IElectronService,
@IWorkbenchEnvironmentService private readonly _environmentService: INativeWorkbenchEnvironmentService
) {
super('report.slow', localize('cmd.report', "Report Issue"));
}
......@@ -129,12 +133,13 @@ class ReportExtensionSlowAction extends Action {
// rewrite pii (paths) and store on disk
const profiler = await import('v8-inspect-profiler');
const data = profiler.rewriteAbsolutePaths({ profile: <any>this.profile.data }, 'pii_removed');
const path = join(os.homedir(), `${this.extension.identifier.value}-unresponsive.cpuprofile.txt`);
const path = joinPath(this._environmentService.tmpDir, `${this.extension.identifier.value}-unresponsive.cpuprofile.txt`).fsPath;
await profiler.writeProfile(data, path).then(undefined, onUnexpectedError);
// build issue
const os = await this._electronService.getOSProperties();
const title = encodeURIComponent('Extension causes high cpu load');
const osVersion = `${os.type()} ${os.arch()} ${os.release()}`;
const osVersion = `${os.type} ${os.arch} ${os.release}`;
const message = `:warning: Make sure to **attach** this file from your *home*-directory:\n:warning:\`${path}\`\n\nFind more details here: https://github.com/microsoft/vscode/wiki/Explain-extension-causes-high-cpu-load`;
const body = encodeURIComponent(`- Issue Type: \`Performance\`
- Extension Name: \`${this.extension.name}\`
......@@ -161,7 +166,8 @@ class ShowExtensionSlowAction extends Action {
readonly repoInfo: RepoInfo,
readonly profile: IExtensionHostProfile,
@IDialogService private readonly _dialogService: IDialogService,
@IOpenerService private readonly _openerService: IOpenerService
@IOpenerService private readonly _openerService: IOpenerService,
@IWorkbenchEnvironmentService private readonly _environmentService: INativeWorkbenchEnvironmentService
) {
super('show.slow', localize('cmd.show', "Show Issues"));
}
......@@ -171,7 +177,7 @@ class ShowExtensionSlowAction extends Action {
// rewrite pii (paths) and store on disk
const profiler = await import('v8-inspect-profiler');
const data = profiler.rewriteAbsolutePaths({ profile: <any>this.profile.data }, 'pii_removed');
const path = join(os.homedir(), `${this.extension.identifier.value}-unresponsive.cpuprofile.txt`);
const path = joinPath(this._environmentService.tmpDir, `${this.extension.identifier.value}-unresponsive.cpuprofile.txt`).fsPath;
await profiler.writeProfile(data, path).then(undefined, onUnexpectedError);
// show issues
......
......@@ -4,14 +4,13 @@
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import * as os from 'os';
import * as path from 'vs/base/common/path';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import * as errors from 'vs/base/common/errors';
import { Schemas } from 'vs/base/common/network';
import * as objects from 'vs/base/common/objects';
import * as platform from 'vs/base/common/platform';
import { originalFSPath } from 'vs/base/common/resources';
import { joinPath, originalFSPath } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import * as pfs from 'vs/base/node/pfs';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
......@@ -264,7 +263,7 @@ export class CachedExtensionScanner {
if (devMode) {
const builtInExtensions = Promise.resolve<IBuiltInExtension[]>(productService.builtInExtensions || []);
const controlFilePath = path.join(os.homedir(), '.vscode-oss-dev', 'extensions', 'control.json');
const controlFilePath = joinPath(environmentService.userHome, '.vscode-oss-dev', 'extensions', 'control.json').fsPath;
const controlFile = pfs.readFile(controlFilePath, 'utf8')
.then<IBuiltInExtensionControl>(raw => JSON.parse(raw), () => ({} as any));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册