summaryrefslogtreecommitdiffhomepage
path: root/gui/src
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2021-10-01 13:24:33 +0200
committerOskar Nyberg <oskar@mullvad.net>2021-10-01 13:24:33 +0200
commit2cc8932c76a2546574f138bf95b88a9978fb0eb8 (patch)
treea6b86a49a635184244827854be9b783209629083 /gui/src
parent26ca38a9520b39ac45102dd7473a965af6220bd6 (diff)
parentc32d5d1a3a437318e11c5b5f448a02b042bde69a (diff)
downloadmullvadvpn-2cc8932c76a2546574f138bf95b88a9978fb0eb8.tar.xz
mullvadvpn-2cc8932c76a2546574f138bf95b88a9978fb0eb8.zip
Merge branch 'update-to-electron-15'
Diffstat (limited to 'gui/src')
-rw-r--r--gui/src/main/daemon-rpc.ts2
-rw-r--r--gui/src/main/index.ts23
-rw-r--r--gui/src/renderer/app.tsx29
-rw-r--r--gui/src/renderer/components/SvgMap.tsx4
-rw-r--r--gui/src/renderer/components/Switch.tsx15
-rw-r--r--gui/src/renderer/components/TransitionContainer.tsx2
-rw-r--r--gui/src/renderer/components/WireguardKeys.tsx2
7 files changed, 34 insertions, 43 deletions
diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts
index 89360fbc15..9df81f119e 100644
--- a/gui/src/main/daemon-rpc.ts
+++ b/gui/src/main/daemon-rpc.ts
@@ -125,7 +125,7 @@ export class DaemonRpc {
private connectionObservers: ConnectionObserver[] = [];
private nextSubscriptionId = 0;
private subscriptions: Map<number, grpc.ClientReadableStream<grpcTypes.DaemonEvent>> = new Map();
- private reconnectionTimeout?: number;
+ private reconnectionTimeout?: NodeJS.Timer;
constructor(connectionParams: string) {
this.client = (new ManagementServiceClient(
diff --git a/gui/src/main/index.ts b/gui/src/main/index.ts
index 3421e72894..b211d9fe12 100644
--- a/gui/src/main/index.ts
+++ b/gui/src/main/index.ts
@@ -1,4 +1,5 @@
import { exec, execFile } from 'child_process';
+import { randomUUID } from 'crypto';
import {
app,
BrowserWindow,
@@ -15,7 +16,6 @@ import os from 'os';
import * as path from 'path';
import { sprintf } from 'sprintf-js';
import util from 'util';
-import * as uuid from 'uuid';
import config from '../config.json';
import { closeToExpiry, hasExpired } from '../shared/account-expiry';
import { IApplication } from '../shared/application-types';
@@ -95,6 +95,8 @@ const UPDATE_NOTIFICATION_DISABLED = process.env.MULLVAD_DISABLE_UPDATE_NOTIFICA
const SANDBOX_DISABLED = app.commandLine.hasSwitch('no-sandbox');
+const ALLOWED_PERMISSIONS = ['clipboard-sanitized-write'];
+
enum AppQuitStage {
unready,
initiated,
@@ -438,8 +440,8 @@ class ApplicationMain {
this.blockPermissionRequests();
// Blocks any http(s) and file requests that aren't supposed to happen.
this.blockRequests();
- // Blocks navigation since it's not needed.
- this.blockNavigation();
+ // Blocks navigation and window.open since it's not needed.
+ this.blockNavigationAndWindowOpen();
this.updateCurrentLocale();
@@ -1289,7 +1291,7 @@ class ApplicationMain {
});
IpcMainEventChannel.problemReport.handleCollectLogs((toRedact) => {
- const id = uuid.v4();
+ const id = randomUUID();
const reportPath = this.getProblemReportPath(id);
const executable = resolveBin('mullvad-problem-report');
const args = ['collect', '--output', reportPath];
@@ -1597,7 +1599,9 @@ class ApplicationMain {
session.defaultSession.setPermissionRequestHandler((_webContents, _permission, callback) => {
callback(false);
});
- session.defaultSession.setPermissionCheckHandler(() => false);
+ session.defaultSession.setPermissionCheckHandler((_webContents, permission) =>
+ ALLOWED_PERMISSIONS.includes(permission),
+ );
}
// Since the app frontend never performs any network requests, all requests originating from the
@@ -1648,11 +1652,11 @@ class ApplicationMain {
);
}
- private blockNavigation() {
+ // Blocks navigation and window.open since it's not needed.
+ private blockNavigationAndWindowOpen() {
app.on('web-contents-created', (_event, contents) => {
- contents.on('will-navigate', (event) => {
- event.preventDefault();
- });
+ contents.on('will-navigate', (event) => event.preventDefault());
+ contents.setWindowOpenHandler(() => ({ action: 'deny' }));
});
}
@@ -1721,7 +1725,6 @@ class ApplicationMain {
nodeIntegration: false,
nodeIntegrationInWorker: false,
nodeIntegrationInSubFrames: false,
- enableRemoteModule: false,
sandbox: !SANDBOX_DISABLED,
contextIsolation: true,
spellcheck: false,
diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx
index c8950f88c8..c37f52bd4f 100644
--- a/gui/src/renderer/app.tsx
+++ b/gui/src/renderer/app.tsx
@@ -47,34 +47,7 @@ import { LogLevel } from '../shared/logging-types';
import IpcOutput from './lib/logging';
import { RoutePath } from './lib/routes';
-// This function wraps all IPC calls to catch errors and then rethrow them without the
-// "Uncaught Error:" prefix that's added by Electron.
-// This is a temporary workaround which won't be required after this Electron PR has been merged and
-// released: https://github.com/electron/electron/pull/28346
-function handleReponse(ipc: typeof window.ipc): typeof window.ipc {
- const wrappedIpc: Record<string, Record<string, unknown>> = {};
-
- Object.entries(ipc).forEach(([groupName, group]) => {
- wrappedIpc[groupName] = {} as typeof group;
-
- Object.entries(group).forEach(([fnName, fn]) => {
- wrappedIpc[groupName][fnName] = (...args: Parameters<typeof fn>) => {
- const response = fn(...args);
- if (response instanceof Promise) {
- return response.catch((error: Error) => {
- throw new Error(error.message?.replace(/^Uncaught Error: /, ''));
- });
- } else {
- return response;
- }
- };
- });
- });
-
- return wrappedIpc as typeof window.ipc;
-}
-
-const IpcRendererEventChannel = handleReponse(window.ipc);
+const IpcRendererEventChannel = window.ipc;
interface IPreferredLocaleDescriptor {
name: string;
diff --git a/gui/src/renderer/components/SvgMap.tsx b/gui/src/renderer/components/SvgMap.tsx
index cae3c68ed6..b72ea36bbd 100644
--- a/gui/src/renderer/components/SvgMap.tsx
+++ b/gui/src/renderer/components/SvgMap.tsx
@@ -31,8 +31,10 @@ const mapStyle = {
height: '100%',
backgroundColor: '#192e45',
};
-const zoomableGroupStyle = {
+const zoomableGroupStyle: React.CSSProperties = {
transition: `transform ${MOVE_SPEED}ms ease-out`,
+ // Workaround to prevent map blurryness in Electron 13+
+ zoom: '100.01%',
};
function getMarkerImageStyle(zoom: number) {
diff --git a/gui/src/renderer/components/Switch.tsx b/gui/src/renderer/components/Switch.tsx
index 0f90a4e7e1..e3b722c721 100644
--- a/gui/src/renderer/components/Switch.tsx
+++ b/gui/src/renderer/components/Switch.tsx
@@ -17,6 +17,9 @@ interface IProps {
interface IState {
isOn: boolean;
isPressed: boolean;
+ // gRPC calls cause the transition to glitch for some reason. Waiting with the onchange event
+ // until after the transition prevents the visual glitch from happening.
+ notifyOnTransitionEnd: boolean;
}
const PAN_DISTANCE = 10;
@@ -56,6 +59,7 @@ export default class Switch extends React.PureComponent<IProps, IState> {
public state: IState = {
isOn: this.props.isOn,
isPressed: false,
+ notifyOnTransitionEnd: false,
};
private containerRef = React.createRef<HTMLDivElement>();
@@ -93,6 +97,7 @@ export default class Switch extends React.PureComponent<IProps, IState> {
isOn={this.state.isOn}
isPressed={this.state.isPressed}
onMouseDown={this.handleMouseDown}
+ onTransitionEnd={this.onTransitionEnd}
/>
</SwitchContainer>
);
@@ -103,13 +108,19 @@ export default class Switch extends React.PureComponent<IProps, IState> {
assignToRef(element, this.props.forwardedRef);
};
+ private onTransitionEnd = (event: React.TransitionEvent) => {
+ if (this.state.notifyOnTransitionEnd && event.propertyName === 'left') {
+ this.notify();
+ }
+ };
+
private handleClick = () => {
if (this.props.disabled) {
return;
}
if (!this.changedDuringPan) {
- this.setState((state) => ({ isOn: !state.isOn }), this.notify);
+ this.setState((state) => ({ isOn: !state.isOn, notifyOnTransitionEnd: true }));
}
// Needs to be reset to allow clicks on container after panning.
@@ -161,7 +172,7 @@ export default class Switch extends React.PureComponent<IProps, IState> {
if (this.state.isOn !== nextOn) {
this.startPos = event.clientX;
this.changedDuringPan = true;
- this.setState({ isOn: nextOn });
+ this.setState({ isOn: nextOn, notifyOnTransitionEnd: false });
}
}
};
diff --git a/gui/src/renderer/components/TransitionContainer.tsx b/gui/src/renderer/components/TransitionContainer.tsx
index 1d177319c2..92aec7828e 100644
--- a/gui/src/renderer/components/TransitionContainer.tsx
+++ b/gui/src/renderer/components/TransitionContainer.tsx
@@ -67,6 +67,8 @@ export const StyledTransitionView = styled.div({
display: 'flex',
flex: 1,
flexDirection: 'column',
+ height: '100%',
+ width: '100%',
});
export class TransitionView extends React.Component<ITransitioningViewProps> {
diff --git a/gui/src/renderer/components/WireguardKeys.tsx b/gui/src/renderer/components/WireguardKeys.tsx
index e76820b006..4a45d58d36 100644
--- a/gui/src/renderer/components/WireguardKeys.tsx
+++ b/gui/src/renderer/components/WireguardKeys.tsx
@@ -68,7 +68,7 @@ export default class WireguardKeys extends React.Component<IProps, IState> {
public componentDidMount() {
this.verifyKey();
- this.keyAgeUpdateInterval = setInterval(this.setAgeOfKeyStringState, 60 * 1000);
+ this.keyAgeUpdateInterval = window.setInterval(this.setAgeOfKeyStringState, 60 * 1000);
}
public componentWillUnmount() {