Skip to content

Commit 53546a4

Browse files
committed
Merge remote-tracking branch 'upstream/main'
2 parents fe2aee4 + fef29bd commit 53546a4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1894
-322
lines changed

package-lock.json

Lines changed: 182 additions & 81 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
"har-validator": "^5.1.3",
9999
"http-encoding": "^2.0.1",
100100
"js-beautify": "^1.8.8",
101+
"jsonc-parser": "^3.3.1",
101102
"jsonwebtoken": "^8.4.0",
102103
"localforage": "^1.7.3",
103104
"lodash": "^4.17.21",

src/components/common/duration-pill.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import * as React from 'react';
22
import { observer } from 'mobx-react';
33

4-
import { TimingEvents } from '../../types';
5-
import { observableClock } from '../../util/observable';
6-
74
import { Pill } from './pill';
5+
86
import { calculateAndFormatDuration, FormattedDurationProps } from "../../util/utils";
97

108
type DurationPillProps = { className?: string } & FormattedDurationProps;

src/components/common/editable-pairs.tsx

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ interface EditablePairsProps<R = PairsArray> {
3232
keyTitle?: string;
3333
// Either a pattern string, or a validation function
3434
keyValidation?: string | ((key: string) => true | string);
35+
valueValidation?: string | ((value: string) => true | string);
3536

3637
keyPlaceholder: string;
3738
valuePlaceholder: string;
@@ -116,23 +117,30 @@ export class EditablePairs<R> extends React.Component<EditablePairsProps<R>> {
116117
));
117118

118119
disposeOnUnmount(this, autorun(() => {
119-
const { keyValidation } = this.props;
120-
if (!_.isFunction(keyValidation)) return;
120+
let { keyValidation, valueValidation } = this.props;
121+
if (!_.isFunction(keyValidation) && !_.isFunction(valueValidation)) return;
121122

122123
const inputs = this.containerRef?.current?.querySelectorAll('input');
123124
if (!inputs) return;
124125

125126
this.values.forEach((pair, i) => {
126127
const keyInput = inputs?.[i * 2];
127-
const validationResult = keyValidation(pair.key);
128-
129-
if (validationResult === true) {
130-
keyInput.setCustomValidity('');
131-
keyInput.reportValidity();
132-
} else {
133-
keyInput.setCustomValidity(validationResult);
134-
keyInput.reportValidity();
135-
}
128+
const valueInput = inputs?.[i * 2 + 1];
129+
130+
([
131+
[ keyInput, pair.key, keyValidation ],
132+
[ valueInput, pair.value, valueValidation ]
133+
] as const).forEach(([input, value, validation]) => {
134+
if (!input || !_.isFunction(validation)) return;
135+
const result = validation(value);
136+
if (result === true) {
137+
input.setCustomValidity('');
138+
} else {
139+
input.setCustomValidity(result);
140+
}
141+
142+
input.reportValidity();
143+
});
136144
});
137145
}));
138146
}

src/components/component-utils.tsx

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,32 @@ export const noPropagation = <E extends React.BaseSyntheticEvent>(
2323
callback(event);
2424
}
2525

26+
/**
27+
* An input validation function combines check logic with an explanatory error
28+
* message, and provides a convenient mechanism to check the validity of an
29+
* input itself (in which case it sets the input's validity state) or a raw
30+
* input value (in which case it just returns the result, with no side effects).
31+
*/
32+
export interface InputValidationFunction {
33+
(input: HTMLInputElement | string): boolean;
34+
}
35+
2636
export const inputValidation = (
2737
checkFn: (input: string) => boolean,
2838
errorMessage: string
29-
) => (input: HTMLInputElement) => {
30-
const inputValue = input.value;
31-
if (!inputValue || checkFn(inputValue)) {
32-
input.setCustomValidity('');
39+
): InputValidationFunction => (input) => {
40+
const isInput = typeof input !== 'string';
41+
const inputValue = isInput ? input.value : input;
42+
43+
if (isInput) {
44+
if (!inputValue || checkFn(inputValue)) {
45+
input.setCustomValidity('');
46+
} else {
47+
input.setCustomValidity(errorMessage);
48+
}
49+
input.reportValidity();
50+
return input.validity.valid;
3351
} else {
34-
input.setCustomValidity(errorMessage);
52+
return checkFn(inputValue);
3553
}
36-
input.reportValidity();
37-
return input.validity.valid;
3854
}

src/components/editor/base-editor.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,13 @@ class BaseEditor extends React.Component<EditorProps> {
260260
new this.monaco.Selection(0, 0, 0, 0)
261261
);
262262

263-
this.relayout();
263+
if (!this.props.value) {
264+
// If we've been cleared, make sure that content update fires before we
265+
// attempt to relayout, to ensure we don't bother laying out an empty editor.
266+
requestAnimationFrame(() => this.relayout());
267+
} else {
268+
this.relayout();
269+
}
264270

265271
requestAnimationFrame(() => {
266272
if (this.editor && this.monaco) {

src/components/editor/monaco.ts

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import type * as MonacoTypes from 'monaco-editor';
22
import type { default as _MonacoEditor, MonacoEditorProps } from 'react-monaco-editor';
3+
import { observable, runInAction } from 'mobx';
34

45
import { defineMonacoThemes } from '../../styles';
56

67
import { delay } from '../../util/promise';
78
import { asError } from '../../util/error';
8-
import { observable, runInAction } from 'mobx';
9-
import { setupXMLValidation } from './xml-validation';
9+
10+
import { ContentValidator, validateJsonRecords, validateXml } from '../../model/events/content-validation';
1011

1112
export type {
1213
MonacoTypes,
@@ -75,7 +76,12 @@ async function loadMonacoEditor(retries = 5): Promise<void> {
7576
},
7677
});
7778

78-
setupXMLValidation(monaco);
79+
monaco.languages.register({
80+
id: 'json-records'
81+
});
82+
83+
addValidator(monaco, 'xml', validateXml);
84+
addValidator(monaco, 'json-records', validateJsonRecords);
7985

8086
MonacoEditor = rmeModule.default;
8187
} catch (err) {
@@ -89,6 +95,43 @@ async function loadMonacoEditor(retries = 5): Promise<void> {
8995
}
9096
}
9197

98+
function addValidator(monaco: typeof MonacoTypes, modeId: string, validator: ContentValidator) {
99+
function validate(model: MonacoTypes.editor.ITextModel) {
100+
const text = model.getValue();
101+
const markers = validator(text, model);
102+
monaco.editor.setModelMarkers(model, modeId, markers);
103+
}
104+
105+
const contentChangeListeners = new Map<MonacoTypes.editor.ITextModel, MonacoTypes.IDisposable>();
106+
107+
function manageContentChangeListener(model: MonacoTypes.editor.ITextModel) {
108+
const isActiveMode = model.getModeId() === modeId;
109+
const listener = contentChangeListeners.get(model);
110+
111+
if (isActiveMode && !listener) {
112+
contentChangeListeners.set(model, model.onDidChangeContent(() =>
113+
validate(model)
114+
));
115+
validate(model);
116+
} else if (!isActiveMode && listener) {
117+
listener.dispose();
118+
contentChangeListeners.delete(model);
119+
monaco.editor.setModelMarkers(model, modeId, []);
120+
}
121+
}
122+
123+
monaco.editor.onWillDisposeModel(model => {
124+
contentChangeListeners.delete(model);
125+
});
126+
monaco.editor.onDidChangeModelLanguage(({ model }) => {
127+
manageContentChangeListener(model);
128+
});
129+
monaco.editor.onDidCreateModel(model => {
130+
manageContentChangeListener(model);
131+
});
132+
133+
}
134+
92135
export function reloadMonacoEditor() {
93136
return monacoLoadingPromise = loadMonacoEditor(0);
94137
}

src/components/editor/xml-validation.ts

Lines changed: 0 additions & 58 deletions
This file was deleted.

src/components/intercept/config/frida-config.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ class FridaConfig extends React.Component<{
253253
}));
254254

255255
this.updateTargets();
256-
const updateInterval = setInterval(this.updateTargets, 2000);
256+
const updateInterval = setInterval(this.updateTargets, 4000);
257257
disposeOnUnmount(this, () => clearInterval(updateInterval));
258258
}
259259

@@ -394,7 +394,8 @@ class FridaConfig extends React.Component<{
394394
this.props.activateInterceptor({
395395
action: 'intercept',
396396
hostId: host.id,
397-
targetId
397+
targetId,
398+
enableSocks: this.props.accountStore!.featureFlags.includes('raw-tunnels')
398399
})
399400
.catch((e) => alertActivationError(`intercept ${targetId}`, e))
400401
.then(() => {

0 commit comments

Comments
 (0)