Add ability to disable JS in response webview

This commit is contained in:
Gregory Schier committed 2019-12-17 14:10:42 -05:00
1 parent 851e142136
commit 3e3886205b
9 files changed
+151 -101

No files matched your search

+57 -53
View File
@@ -6,43 +6,44 @@ import { UPDATE_CHANNEL_STABLE } from '../common/constants';
import * as hotkeys from '../common/hotkeys';
type BaseSettings = {
showPasswords: boolean,
useBulkHeaderEditor: boolean,
useBulkParametersEditor: boolean,
followRedirects: boolean,
autoHideMenuBar: boolean,
autocompleteDelay: number,
deviceId: string | null,
disableHtmlPreviewJs: boolean,
disableUpdateNotification: boolean,
editorFontSize: number,
editorIndentSize: number,
editorLineWrapping: boolean,
editorKeyMap: string,
editorIndentWithTabs: boolean,
httpProxy: string,
httpsProxy: string,
noProxy: string,
proxyEnabled: boolean,
timeout: number,
validateSSL: boolean,
forceVerticalLayout: boolean,
autoHideMenuBar: boolean,
theme: string,
maxRedirects: number,
maxHistoryResponses: number,
pluginPath: string,
nunjucksPowerUserMode: boolean,
deviceId: string | null,
updateChannel: string,
updateAutomatically: boolean,
disableUpdateNotification: boolean,
editorKeyMap: string,
editorLineWrapping: boolean,
environmentHighlightColorStyle: string,
autocompleteDelay: number,
fontMonospace: string | null,
followRedirects: boolean,
fontInterface: string | null,
fontMonospace: string | null,
fontSize: number,
fontVariantLigatures: boolean,
forceVerticalLayout: boolean,
hotKeyRegistry: hotkeys.HotKeyRegistry,
httpProxy: string,
httpsProxy: string,
maxHistoryResponses: number,
maxRedirects: number,
maxTimelineDataSizeKB: number,
noProxy: string,
nunjucksPowerUserMode: boolean,
pluginPath: string,
proxyEnabled: boolean,
showPasswords: boolean,
theme: string,
timeout: number,
updateAutomatically: boolean,
updateChannel: string,
useBulkHeaderEditor: boolean,
useBulkParametersEditor: boolean,
validateSSL: boolean,
// Feature flags
enableSyncBeta: boolean,
hotKeyRegistry: hotkeys.HotKeyRegistry,
};
export type Settings = BaseModel & BaseSettings;
@@ -55,41 +56,44 @@ export const canSync = false;
export function init(): BaseSettings {
return {
showPasswords: false,
useBulkHeaderEditor: false,
useBulkParametersEditor: false,
followRedirects: true,
autoHideMenuBar: false,
autocompleteDelay: 1200,
deviceId: null,
disableHtmlPreviewJs: false,
disableUpdateNotification: false,
editorFontSize: 11,
editorIndentSize: 2,
editorLineWrapping: true,
editorKeyMap: 'default',
editorIndentWithTabs: true,
httpProxy: '',
httpsProxy: '',
noProxy: '',
maxRedirects: -1,
maxHistoryResponses: 20,
proxyEnabled: false,
timeout: 0,
validateSSL: true,
forceVerticalLayout: false,
autoHideMenuBar: false,
theme: packageJson.app.theme,
pluginPath: '',
nunjucksPowerUserMode: false,
deviceId: null,
updateChannel: UPDATE_CHANNEL_STABLE,
updateAutomatically: true,
disableUpdateNotification: false,
editorKeyMap: 'default',
editorLineWrapping: true,
environmentHighlightColorStyle: 'sidebar-indicator',
autocompleteDelay: 1200,
fontMonospace: null,
followRedirects: true,
fontInterface: null,
fontMonospace: null,
fontSize: 13,
fontVariantLigatures: false,
maxTimelineDataSizeKB: 10,
enableSyncBeta: false,
forceVerticalLayout: false,
hotKeyRegistry: hotkeys.newDefaultRegistry(),
httpProxy: '',
httpsProxy: '',
maxHistoryResponses: 20,
maxRedirects: -1,
maxTimelineDataSizeKB: 10,
noProxy: '',
nunjucksPowerUserMode: false,
pluginPath: '',
proxyEnabled: false,
showPasswords: false,
theme: packageJson.app.theme,
timeout: 0,
updateAutomatically: true,
updateChannel: UPDATE_CHANNEL_STABLE,
useBulkHeaderEditor: false,
useBulkParametersEditor: false,
validateSSL: true,
// Feature flags
enableSyncBeta: false,
};
}
@@ -45,6 +45,7 @@ type Props = {
previewMode: string,
filter: string,
filterHistory: Array<string>,
disableHtmlPreviewJs: boolean,
editorFontSize: number,
editorIndentSize: number,
editorKeyMap: string,
@@ -176,26 +177,27 @@ class ResponsePane extends React.PureComponent<Props> {
render() {
const {
request,
responses,
requestVersions,
response,
previewMode,
handleShowRequestSettings,
handleSetPreviewMode,
handleSetActiveResponse,
handleDeleteResponses,
handleDeleteResponse,
handleSetFilter,
loadStartTime,
editorLineWrapping,
disableHtmlPreviewJs,
editorFontSize,
editorIndentSize,
editorKeyMap,
editorLineWrapping,
filter,
filterHistory,
showCookiesModal,
handleDeleteResponse,
handleDeleteResponses,
handleSetActiveResponse,
handleSetFilter,
handleSetPreviewMode,
handleShowRequestSettings,
hotKeyRegistry,
loadStartTime,
previewMode,
request,
requestVersions,
response,
responses,
showCookiesModal,
} = this.props;
const paneClasses = 'response-pane theme--pane pane';
@@ -343,6 +345,7 @@ class ResponsePane extends React.PureComponent<Props> {
filterHistory={filterHistory}
updateFilter={response.error ? null : handleSetFilter}
download={this._handleDownloadResponseBody}
disableHtmlPreviewJs={disableHtmlPreviewJs}
getBody={this._handleGetResponseBody}
error={response.error}
editorLineWrapping={editorLineWrapping}
@@ -301,10 +301,17 @@ class General extends React.PureComponent<Props, State> {
<hr className="pad-top" />
<h2>Network</h2>
<h2>Request / Response</h2>
{this.renderBooleanSetting('Validate certificates', 'validateSSL', '')}
{this.renderBooleanSetting('Follow redirects', 'followRedirects', '')}
<div className="row-fill row-fill--top">
<div>
{this.renderBooleanSetting('Validate certificates', 'validateSSL', '')}
{this.renderBooleanSetting('Follow redirects', 'followRedirects', '')}
</div>
<div>
{this.renderBooleanSetting('Disable JS in HTML preview', 'disableHtmlPreviewJs', '')}
</div>
</div>
<div className="form-row pad-top-sm">
{this.renderNumberSetting('Maximum Redirects', 'maxRedirects', '-1 for infinite', {
@@ -29,6 +29,7 @@ type Props = {
responseId: string,
bodyBuffer: Buffer | null,
contentType: string,
disableHtmlPreviewJs: boolean,
filter: string,
filterHistory: Array<string>,
editorFontSize: number,
@@ -215,6 +216,7 @@ class ResponseMultipart extends React.PureComponent<Props, State> {
render() {
const {
download,
disableHtmlPreviewJs,
editorFontSize,
editorIndentSize,
editorKeyMap,
@@ -282,6 +284,7 @@ class ResponseMultipart extends React.PureComponent<Props, State> {
bytes={selectedPart.bytes || 0}
contentType={getContentTypeFromHeaders(selectedPart.headers, 'text/plain')}
download={download}
disableHtmlPreviewJs={disableHtmlPreviewJs}
editorFontSize={editorFontSize}
editorIndentSize={editorIndentSize}
editorKeyMap={editorKeyMap}
@@ -36,6 +36,7 @@ type Props = {
url: string,
bytes: number,
contentType: string,
disableHtmlPreviewJs: boolean,
// Optional
updateFilter: Function | null,
@@ -194,6 +195,7 @@ class ResponseViewer extends React.Component<Props, State> {
_renderView() {
const {
bytes,
disableHtmlPreviewJs,
download,
editorFontSize,
editorIndentSize,
@@ -318,7 +320,9 @@ class ResponseViewer extends React.Component<Props, State> {
<ResponseWebView
body={this._decodeIconv(bodyBuffer, charset)}
contentType={contentType}
key={disableHtmlPreviewJs ? 'no-js' : 'yes-js'}
url={url}
webpreferences={disableHtmlPreviewJs ? 'javascript=no' : 'javascript=yes'}
/>
);
} else if (previewMode === PREVIEW_MODE_FRIENDLY && ct.indexOf('application/pdf') === 0) {
@@ -336,9 +340,9 @@ class ResponseViewer extends React.Component<Props, State> {
} else if (previewMode === PREVIEW_MODE_FRIENDLY && ct.indexOf('multipart/') === 0) {
return (
<MultipartViewer
key={responseId}
bodyBuffer={bodyBuffer}
contentType={contentType}
disableHtmlPreviewJs={disableHtmlPreviewJs}
download={download}
editorFontSize={editorFontSize}
editorIndentSize={editorIndentSize}
@@ -346,6 +350,7 @@ class ResponseViewer extends React.Component<Props, State> {
editorLineWrapping={editorLineWrapping}
filter={filter}
filterHistory={filterHistory}
key={responseId}
responseId={responseId}
url={url}
/>
@@ -1,50 +1,67 @@
import React, { PureComponent } from 'react';
// @flow
import * as React from 'react';
import { EventEmitter } from 'events';
import PropTypes from 'prop-types';
import autobind from 'autobind-decorator';
import contextMenu from 'electron-context-menu';
type Props = {
body: string,
contentType: string,
url: string,
webpreferences: string,
};
@autobind
class ResponseWebView extends PureComponent {
_handleSetWebViewRef(n) {
class ResponseWebView extends React.PureComponent<Props> {
_webview: ?HTMLElement;
_handleSetWebViewRef(n: ?HTMLElement) {
this._webview = n;
if (this._webview) {
this._webview.addEventListener('dom-ready', this._handleDOMReady);
}
}
_handleDOMReady() {
if (!this._webview) {
return;
}
this._webview.removeEventListener('dom-ready', this._handleDOMReady);
contextMenu({ window: this._webview });
this._setBody();
}
_setBody() {
const webview: Object = this._webview;
if (!webview) {
return;
}
const { body, contentType, url } = this.props;
this._webview.loadURL(`data:${contentType},${encodeURIComponent(body)}`, {
webview.loadURL(`data:${contentType},${encodeURIComponent(body)}`, {
baseURLForDataURL: url,
});
// This is kind of hacky but electron-context-menu fails to save images if
// this isn't here.
this._webview.webContents = this._webview;
this._webview.webContents.session = new EventEmitter();
webview.webContents = webview;
webview.webContents.session = new EventEmitter();
}
componentDidUpdate() {
this._setBody();
}
componentDidMount() {
this._webview.addEventListener('dom-ready', this._handleDOMReady);
}
render() {
return <webview ref={this._handleSetWebViewRef} src="about:blank" />;
const { webpreferences } = this.props;
return (
<webview ref={this._handleSetWebViewRef} src="about:blank" webpreferences={webpreferences} />
);
}
}
ResponseWebView.propTypes = {
body: PropTypes.string.isRequired,
contentType: PropTypes.string.isRequired,
url: PropTypes.string.isRequired,
};
export default ResponseWebView;
@@ -847,26 +847,27 @@ class Wrapper extends React.PureComponent<Props, State> {
<ErrorBoundary showAlert>
<ResponsePane
ref={handleSetResponsePaneRef}
request={activeRequest}
requestVersions={requestVersions}
responses={activeRequestResponses}
response={activeResponse}
disableHtmlPreviewJs={settings.disableHtmlPreviewJs}
editorFontSize={settings.editorFontSize}
editorIndentSize={settings.editorIndentSize}
editorKeyMap={settings.editorKeyMap}
editorLineWrapping={settings.editorLineWrapping}
hotKeyRegistry={settings.hotKeyRegistry}
previewMode={responsePreviewMode}
filter={responseFilter}
filterHistory={responseFilterHistory}
loadStartTime={loadStartTime}
showCookiesModal={this._handleShowCookiesModal}
handleShowRequestSettings={this._handleShowRequestSettingsModal}
handleSetActiveResponse={this._handleSetActiveResponse}
handleSetPreviewMode={this._handleSetPreviewMode}
handleDeleteResponses={this._handleDeleteResponses}
handleDeleteResponse={this._handleDeleteResponse}
handleDeleteResponses={this._handleDeleteResponses}
handleSetActiveResponse={this._handleSetActiveResponse}
handleSetFilter={this._handleSetResponseFilter}
handleSetPreviewMode={this._handleSetPreviewMode}
handleShowRequestSettings={this._handleShowRequestSettingsModal}
hotKeyRegistry={settings.hotKeyRegistry}
loadStartTime={loadStartTime}
previewMode={responsePreviewMode}
request={activeRequest}
requestVersions={requestVersions}
response={activeResponse}
responses={activeRequestResponses}
showCookiesModal={this._handleShowCookiesModal}
/>
</ErrorBoundary>
</div>,
@@ -0,0 +1,5 @@
// @flow
declare module 'electron-context-menu' {
declare module.exports: ({ window: Window }) => void;
}
+5
View File
@@ -0,0 +1,5 @@
// @flow
declare module 'events' {
declare module.exports: *;
}