diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2021-10-01 13:24:33 +0200 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2021-10-01 13:24:33 +0200 |
| commit | 2cc8932c76a2546574f138bf95b88a9978fb0eb8 (patch) | |
| tree | a6b86a49a635184244827854be9b783209629083 /gui/src | |
| parent | 26ca38a9520b39ac45102dd7473a965af6220bd6 (diff) | |
| parent | c32d5d1a3a437318e11c5b5f448a02b042bde69a (diff) | |
| download | mullvadvpn-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.ts | 2 | ||||
| -rw-r--r-- | gui/src/main/index.ts | 23 | ||||
| -rw-r--r-- | gui/src/renderer/app.tsx | 29 | ||||
| -rw-r--r-- | gui/src/renderer/components/SvgMap.tsx | 4 | ||||
| -rw-r--r-- | gui/src/renderer/components/Switch.tsx | 15 | ||||
| -rw-r--r-- | gui/src/renderer/components/TransitionContainer.tsx | 2 | ||||
| -rw-r--r-- | gui/src/renderer/components/WireguardKeys.tsx | 2 |
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() { |
