summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2020-10-29 13:11:34 +0100
committerOskar Nyberg <oskar@mullvad.net>2020-10-29 13:11:34 +0100
commit392b2a293e34807176adb3e997df3b89445232f0 (patch)
tree7ccb9a6b35d9ef187aadba11ce8f0cfc66f9f1e1
parent02942bb74ad8efa6f1ef255bd0802288032cdb30 (diff)
parentc6c05176f1f5963d1771ac76068629aeaf8560c1 (diff)
downloadmullvadvpn-392b2a293e34807176adb3e997df3b89445232f0.tar.xz
mullvadvpn-392b2a293e34807176adb3e997df3b89445232f0.zip
Merge branch 'improve-eslint-rules-2' into master
-rw-r--r--gui/.eslintrc.js17
-rw-r--r--gui/src/main/daemon-rpc.ts318
-rw-r--r--gui/src/renderer/components/Accordion.tsx6
-rw-r--r--gui/src/renderer/components/AdvancedSettings.tsx8
-rw-r--r--gui/src/renderer/components/Map.tsx4
-rw-r--r--gui/src/renderer/components/Marquee.tsx6
-rw-r--r--gui/src/renderer/components/WireguardKeys.tsx4
7 files changed, 190 insertions, 173 deletions
diff --git a/gui/.eslintrc.js b/gui/.eslintrc.js
index c2cd00afe7..3e12630d7b 100644
--- a/gui/.eslintrc.js
+++ b/gui/.eslintrc.js
@@ -33,6 +33,22 @@ const namingConvention = [
},
];
+const memberOrdering = {
+ default: [
+ 'public-field',
+ 'protected-field',
+ 'private-field',
+
+ 'public-constructor',
+ 'protected-constructor',
+ 'private-constructor',
+
+ 'public-method',
+ 'protected-method',
+ 'private-method',
+ ],
+};
+
module.exports = {
env: {
es6: true,
@@ -71,6 +87,7 @@ module.exports = {
'@typescript-eslint/require-await': 'error',
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/no-unused-expressions': 'error',
+ '@typescript-eslint/member-ordering': ['error', memberOrdering],
'no-return-await': 'error',
'react/jsx-no-bind': 'error',
'@typescript-eslint/naming-convention': ['error', ...namingConvention],
diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts
index 78dae947a0..130651c200 100644
--- a/gui/src/main/daemon-rpc.ts
+++ b/gui/src/main/daemon-rpc.ts
@@ -120,14 +120,6 @@ type CallFunctionArgument<T, R> =
| undefined;
export class DaemonRpc {
- constructor(connectionParams: string) {
- this.client = (new ManagementServiceClient(
- connectionParams,
- grpc.credentials.createInsecure(),
- this.channelOptions(),
- ) as unknown) as managementInterface.ManagementServiceClient;
- }
-
private client: managementInterface.ManagementServiceClient;
private isConnected = false;
private connectionObservers: ConnectionObserver[] = [];
@@ -135,60 +127,12 @@ export class DaemonRpc {
private subscriptions: Map<number, grpc.ClientReadableStream<grpcTypes.DaemonEvent>> = new Map();
private reconnectionTimeout?: number;
- private subscriptionId(): number {
- const current = this.nextSubscriptionId;
- this.nextSubscriptionId += 1;
- return current;
- }
-
- private deadlineFromNow() {
- return Date.now() + NETWORK_CALL_TIMEOUT;
- }
-
- private channelStateTimeout(): number {
- return Date.now() + CHANNEL_STATE_TIMEOUT;
- }
-
- private callEmpty<R>(fn: CallFunctionArgument<Empty, R>): Promise<R> {
- return this.call<Empty, R>(fn, new Empty());
- }
-
- private callString<R>(fn: CallFunctionArgument<StringValue, R>, value?: string): Promise<R> {
- const googleString = new StringValue();
-
- if (value !== undefined) {
- googleString.setValue(value);
- }
-
- return this.call<StringValue, R>(fn, googleString);
- }
-
- private callBool<R>(fn: CallFunctionArgument<BoolValue, R>, value?: boolean): Promise<R> {
- const googleBool = new BoolValue();
-
- if (value !== undefined) {
- googleBool.setValue(value);
- }
-
- return this.call<BoolValue, R>(fn, googleBool);
- }
-
- private callNumber<R>(fn: CallFunctionArgument<UInt32Value, R>, value?: number): Promise<R> {
- const googleNumber = new UInt32Value();
-
- if (value !== undefined) {
- googleNumber.setValue(value);
- }
-
- return this.call<UInt32Value, R>(fn, googleNumber);
- }
-
- private call<T, R>(fn: CallFunctionArgument<T, R>, arg: T): Promise<R> {
- if (fn && this.isConnected) {
- return promisify<T, R>(fn.bind(this.client))(arg);
- } else {
- throw noConnectionError;
- }
+ constructor(connectionParams: string) {
+ this.client = (new ManagementServiceClient(
+ connectionParams,
+ grpc.credentials.createInsecure(),
+ this.channelOptions(),
+ ) as unknown) as managementInterface.ManagementServiceClient;
}
public connect(): Promise<void> {
@@ -209,87 +153,6 @@ export class DaemonRpc {
});
}
- private channelOptions(): grpc.ClientOptions {
- /* eslint-disable @typescript-eslint/naming-convention */
- return {
- 'grpc.max_reconnect_backoff_ms': 3000,
- 'grpc.initial_reconnect_backoff_ms': 3000,
- 'grpc.keepalive_time_ms': Math.pow(2, 30),
- 'grpc.keepalive_timeout_ms': Math.pow(2, 30),
- };
- /* eslint-enable @typescript-eslint/naming-convention */
- }
-
- private connectivityChangeCallback(timeoutErr?: Error) {
- const channel = this.client.getChannel();
- const currentState = channel?.getConnectivityState(true);
- log.debug(`GRPC Channel connectivity state changed to ${currentState}`);
- if (channel) {
- if (timeoutErr) {
- this.setChannelCallback(currentState);
- return;
- }
- const wasConnected = this.isConnected;
- if (this.channelDisconnected(currentState)) {
- this.connectionObservers.forEach((observer) => observer.onClose());
- this.isConnected = false;
- // Try and reconnect in case
- consumePromise(
- this.connect().catch((error) => {
- log.error(`Failed to reconnect - ${error}`);
- }),
- );
- this.setChannelCallback(currentState);
- } else if (!wasConnected && currentState === grpc.connectivityState.READY) {
- this.isConnected = true;
- this.connectionObservers.forEach((observer) => observer.onOpen());
- this.setChannelCallback(currentState);
- }
- }
- }
-
- private channelDisconnected(state: grpc.connectivityState): boolean {
- return (
- (state === grpc.connectivityState.SHUTDOWN ||
- state === grpc.connectivityState.TRANSIENT_FAILURE ||
- state === grpc.connectivityState.IDLE) &&
- this.isConnected
- );
- }
-
- private setChannelCallback(currentState?: grpc.connectivityState) {
- const channel = this.client.getChannel();
- if (currentState === undefined && channel) {
- currentState = channel?.getConnectivityState(false);
- }
- if (currentState) {
- channel.watchConnectivityState(currentState, this.channelStateTimeout(), (error) =>
- this.connectivityChangeCallback(error),
- );
- }
- }
-
- // Since grpc.Channel.watchConnectivityState() isn't always running as intended, whenever the
- // client fails to connect at first, `ensureConnectivity()` should be called so that it tries to
- // check the connectivity state and nudge the client into connecting.
- // `grpc.Channel.getConnectivityState(true)` should make it attempt to connect.
- private ensureConnectivity() {
- this.reconnectionTimeout = setTimeout(() => {
- const lastState = this.client.getChannel().getConnectivityState(true);
- if (this.channelDisconnected(lastState)) {
- this.connectionObservers.forEach((observer) => observer.onClose());
- this.isConnected = false;
- }
- if (!this.isConnected) {
- consumePromise(
- this.connect().catch((error) => {
- log.error(`Failed to reconnect - ${error}`);
- }),
- );
- }
- }, 3000);
- }
-
public disconnect() {
this.isConnected = false;
this.subscriptions.clear();
@@ -562,22 +425,6 @@ export class DaemonRpc {
}
}
- private removeSubscription(id: number) {
- const subscription = this.subscriptions.get(id);
- if (subscription !== undefined) {
- this.subscriptions.delete(id);
- subscription.removeAllListeners('data');
- subscription.removeAllListeners('error');
- try {
- subscription.cancel();
- } catch (error) {
- if (error.code !== grpc.status.CANCELLED) {
- throw error;
- }
- }
- }
- }
-
public async getAccountHistory(): Promise<AccountToken[]> {
const response = await this.callEmpty<grpcTypes.AccountHistory>(this.client.getAccountHistory);
return response.toObject().tokenList;
@@ -614,6 +461,159 @@ export class DaemonRpc {
const response = await this.callEmpty<grpcTypes.AppVersionInfo>(this.client.getVersionInfo);
return response.toObject();
}
+
+ private subscriptionId(): number {
+ const current = this.nextSubscriptionId;
+ this.nextSubscriptionId += 1;
+ return current;
+ }
+
+ private deadlineFromNow() {
+ return Date.now() + NETWORK_CALL_TIMEOUT;
+ }
+
+ private channelStateTimeout(): number {
+ return Date.now() + CHANNEL_STATE_TIMEOUT;
+ }
+
+ private callEmpty<R>(fn: CallFunctionArgument<Empty, R>): Promise<R> {
+ return this.call<Empty, R>(fn, new Empty());
+ }
+
+ private callString<R>(fn: CallFunctionArgument<StringValue, R>, value?: string): Promise<R> {
+ const googleString = new StringValue();
+
+ if (value !== undefined) {
+ googleString.setValue(value);
+ }
+
+ return this.call<StringValue, R>(fn, googleString);
+ }
+
+ private callBool<R>(fn: CallFunctionArgument<BoolValue, R>, value?: boolean): Promise<R> {
+ const googleBool = new BoolValue();
+
+ if (value !== undefined) {
+ googleBool.setValue(value);
+ }
+
+ return this.call<BoolValue, R>(fn, googleBool);
+ }
+
+ private callNumber<R>(fn: CallFunctionArgument<UInt32Value, R>, value?: number): Promise<R> {
+ const googleNumber = new UInt32Value();
+
+ if (value !== undefined) {
+ googleNumber.setValue(value);
+ }
+
+ return this.call<UInt32Value, R>(fn, googleNumber);
+ }
+
+ private call<T, R>(fn: CallFunctionArgument<T, R>, arg: T): Promise<R> {
+ if (fn && this.isConnected) {
+ return promisify<T, R>(fn.bind(this.client))(arg);
+ } else {
+ throw noConnectionError;
+ }
+ }
+
+ private removeSubscription(id: number) {
+ const subscription = this.subscriptions.get(id);
+ if (subscription !== undefined) {
+ this.subscriptions.delete(id);
+ subscription.removeAllListeners('data');
+ subscription.removeAllListeners('error');
+ try {
+ subscription.cancel();
+ } catch (error) {
+ if (error.code !== grpc.status.CANCELLED) {
+ throw error;
+ }
+ }
+ }
+ }
+
+ private channelOptions(): grpc.ClientOptions {
+ /* eslint-disable @typescript-eslint/naming-convention */
+ return {
+ 'grpc.max_reconnect_backoff_ms': 3000,
+ 'grpc.initial_reconnect_backoff_ms': 3000,
+ 'grpc.keepalive_time_ms': Math.pow(2, 30),
+ 'grpc.keepalive_timeout_ms': Math.pow(2, 30),
+ };
+ /* eslint-enable @typescript-eslint/naming-convention */
+ }
+
+ private connectivityChangeCallback(timeoutErr?: Error) {
+ const channel = this.client.getChannel();
+ const currentState = channel?.getConnectivityState(true);
+ log.debug(`GRPC Channel connectivity state changed to ${currentState}`);
+ if (channel) {
+ if (timeoutErr) {
+ this.setChannelCallback(currentState);
+ return;
+ }
+ const wasConnected = this.isConnected;
+ if (this.channelDisconnected(currentState)) {
+ this.connectionObservers.forEach((observer) => observer.onClose());
+ this.isConnected = false;
+ // Try and reconnect in case
+ consumePromise(
+ this.connect().catch((error) => {
+ log.error(`Failed to reconnect - ${error}`);
+ }),
+ );
+ this.setChannelCallback(currentState);
+ } else if (!wasConnected && currentState === grpc.connectivityState.READY) {
+ this.isConnected = true;
+ this.connectionObservers.forEach((observer) => observer.onOpen());
+ this.setChannelCallback(currentState);
+ }
+ }
+ }
+
+ private channelDisconnected(state: grpc.connectivityState): boolean {
+ return (
+ (state === grpc.connectivityState.SHUTDOWN ||
+ state === grpc.connectivityState.TRANSIENT_FAILURE ||
+ state === grpc.connectivityState.IDLE) &&
+ this.isConnected
+ );
+ }
+
+ private setChannelCallback(currentState?: grpc.connectivityState) {
+ const channel = this.client.getChannel();
+ if (currentState === undefined && channel) {
+ currentState = channel?.getConnectivityState(false);
+ }
+ if (currentState) {
+ channel.watchConnectivityState(currentState, this.channelStateTimeout(), (error) =>
+ this.connectivityChangeCallback(error),
+ );
+ }
+ }
+
+ // Since grpc.Channel.watchConnectivityState() isn't always running as intended, whenever the
+ // client fails to connect at first, `ensureConnectivity()` should be called so that it tries to
+ // check the connectivity state and nudge the client into connecting.
+ // `grpc.Channel.getConnectivityState(true)` should make it attempt to connect.
+ private ensureConnectivity() {
+ this.reconnectionTimeout = setTimeout(() => {
+ const lastState = this.client.getChannel().getConnectivityState(true);
+ if (this.channelDisconnected(lastState)) {
+ this.connectionObservers.forEach((observer) => observer.onClose());
+ this.isConnected = false;
+ }
+ if (!this.isConnected) {
+ consumePromise(
+ this.connect().catch((error) => {
+ log.error(`Failed to reconnect - ${error}`);
+ }),
+ );
+ }
+ }, 3000);
+ }
}
function liftConstraint<T>(constraint: Constraint<T> | undefined): T | undefined {
diff --git a/gui/src/renderer/components/Accordion.tsx b/gui/src/renderer/components/Accordion.tsx
index 1a26d765cd..01c0733165 100644
--- a/gui/src/renderer/components/Accordion.tsx
+++ b/gui/src/renderer/components/Accordion.tsx
@@ -29,9 +29,6 @@ const Content = styled.div({
});
export default class Accordion extends React.Component<IProps, IState> {
- private containerRef = React.createRef<HTMLDivElement>();
- private contentRef = React.createRef<HTMLDivElement>();
-
public static defaultProps = {
expanded: true,
animationDuration: 350,
@@ -42,6 +39,9 @@ export default class Accordion extends React.Component<IProps, IState> {
containerHeight: this.props.expanded ? 'auto' : '0',
};
+ private containerRef = React.createRef<HTMLDivElement>();
+ private contentRef = React.createRef<HTMLDivElement>();
+
public componentDidUpdate(oldProps: IProps) {
if (this.props.expanded && !oldProps.expanded) {
this.expand();
diff --git a/gui/src/renderer/components/AdvancedSettings.tsx b/gui/src/renderer/components/AdvancedSettings.tsx
index b044226634..a34b5b499c 100644
--- a/gui/src/renderer/components/AdvancedSettings.tsx
+++ b/gui/src/renderer/components/AdvancedSettings.tsx
@@ -77,15 +77,15 @@ interface IState {
}
export default class AdvancedSettings extends React.Component<IProps, IState> {
+ public state = {
+ showConfirmBlockWhenDisconnectedAlert: false,
+ };
+
private portItems: { [key in RelayProtocol]: Array<ISelectorItem<OptionalPort>> };
private protocolItems: Array<ISelectorItem<OptionalRelayProtocol>>;
private bridgeStateItems: Array<ISelectorItem<BridgeState>>;
private wireguardPortItems: Array<ISelectorItem<OptionalPort>>;
- public state = {
- showConfirmBlockWhenDisconnectedAlert: false,
- };
-
constructor(props: IProps) {
super(props);
diff --git a/gui/src/renderer/components/Map.tsx b/gui/src/renderer/components/Map.tsx
index 8bc78b4b68..ddab985992 100644
--- a/gui/src/renderer/components/Map.tsx
+++ b/gui/src/renderer/components/Map.tsx
@@ -30,8 +30,6 @@ interface IState {
}
export default class Map extends React.Component<IProps, IState> {
- private containerRef = React.createRef<HTMLDivElement>();
-
public state: IState = {
bounds: {
width: 0,
@@ -39,6 +37,8 @@ export default class Map extends React.Component<IProps, IState> {
},
};
+ private containerRef = React.createRef<HTMLDivElement>();
+
public render() {
const { width, height } = this.state.bounds;
const readyToRenderTheMap = width > 0 && height > 0;
diff --git a/gui/src/renderer/components/Marquee.tsx b/gui/src/renderer/components/Marquee.tsx
index d2d5bcbccd..427ab81780 100644
--- a/gui/src/renderer/components/Marquee.tsx
+++ b/gui/src/renderer/components/Marquee.tsx
@@ -30,14 +30,14 @@ interface IMarqueeState {
}
export default class Marquee extends React.Component<IMarqueeProps, IMarqueeState> {
- private textRef = React.createRef<HTMLSpanElement>();
- private scheduler = new Scheduler();
-
public state = {
alignRight: false,
uniqueKey: 0,
};
+ private textRef = React.createRef<HTMLSpanElement>();
+ private scheduler = new Scheduler();
+
public componentDidMount() {
this.startAnimationIfOverflow();
}
diff --git a/gui/src/renderer/components/WireguardKeys.tsx b/gui/src/renderer/components/WireguardKeys.tsx
index d5b0dc1833..9e1df9693c 100644
--- a/gui/src/renderer/components/WireguardKeys.tsx
+++ b/gui/src/renderer/components/WireguardKeys.tsx
@@ -53,14 +53,14 @@ export interface IState {
}
export default class WireguardKeys extends React.Component<IProps, IState> {
- private keyAgeUpdateInterval?: number;
-
public state = {
recentlyGeneratedKey: false,
userHasInitiatedVerification: false,
ageOfKeyString: WireguardKeys.ageOfKeyString(this.props.keyState, this.props.locale),
};
+ private keyAgeUpdateInterval?: number;
+
public static getDerivedStateFromProps(props: IProps) {
return {
ageOfKeyString: WireguardKeys.ageOfKeyString(props.keyState, props.locale),