diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2019-01-23 13:33:14 +0100 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2019-01-23 15:37:57 +0100 |
| commit | b1b35e5b902b7e66b3c86160137be7fbf1d88f92 (patch) | |
| tree | 2d15e2c26e747f8337e2350c90085e1639d9fe0c | |
| parent | 181bbf34c63efdbac6f09b5a1e39944b8acf4196 (diff) | |
| download | mullvadvpn-b1b35e5b902b7e66b3c86160137be7fbf1d88f92.tar.xz mullvadvpn-b1b35e5b902b7e66b3c86160137be7fbf1d88f92.zip | |
Migrate autostart logic to the main process
| -rw-r--r-- | gui/packages/desktop/src/main/autostart.js (renamed from gui/packages/desktop/src/renderer/lib/autostart.js) | 10 | ||||
| -rw-r--r-- | gui/packages/desktop/src/main/index.js | 34 | ||||
| -rw-r--r-- | gui/packages/desktop/src/renderer/app.js | 36 | ||||
| -rw-r--r-- | gui/packages/desktop/src/renderer/components/Preferences.js | 21 | ||||
| -rw-r--r-- | gui/packages/desktop/src/renderer/containers/PreferencesPage.js | 5 | ||||
| -rw-r--r-- | gui/packages/desktop/src/renderer/lib/daemon-rpc-proxy.js | 4 | ||||
| -rw-r--r-- | gui/packages/desktop/src/renderer/redux/settings/actions.js | 16 | ||||
| -rw-r--r-- | gui/packages/desktop/src/renderer/redux/settings/reducers.js | 8 | ||||
| -rw-r--r-- | gui/packages/desktop/src/shared/ipc-event-channel.js | 28 |
9 files changed, 112 insertions, 50 deletions
diff --git a/gui/packages/desktop/src/renderer/lib/autostart.js b/gui/packages/desktop/src/main/autostart.js index 7617b9b13a..614df69350 100644 --- a/gui/packages/desktop/src/renderer/lib/autostart.js +++ b/gui/packages/desktop/src/main/autostart.js @@ -3,7 +3,7 @@ import fs from 'fs'; import path from 'path'; import { promisify } from 'util'; -import { remote } from 'electron'; +import { app } from 'electron'; import log from 'electron-log'; const DESKTOP_FILE_NAME = 'mullvad-vpn.desktop'; @@ -16,7 +16,7 @@ const unlinkAsync = promisify(fs.unlink); export function getOpenAtLogin() { if (process.platform === 'linux') { try { - const autostartDir = path.join(remote.app.getPath('appData'), 'autostart'); + const autostartDir = path.join(app.getPath('appData'), 'autostart'); const autostartFilePath = path.join(autostartDir, DESKTOP_FILE_NAME); fs.accessSync(autostartFilePath); @@ -27,7 +27,7 @@ export function getOpenAtLogin() { return false; } } else { - return remote.app.getLoginItemSettings().openAtLogin; + return app.getLoginItemSettings().openAtLogin; } } @@ -35,7 +35,7 @@ export async function setOpenAtLogin(openAtLogin: boolean) { if (process.platform === 'linux') { try { const desktopFilePath = path.join('/usr/share/applications', DESKTOP_FILE_NAME); - const autostartDir = path.join(remote.app.getPath('appData'), 'autostart'); + const autostartDir = path.join(app.getPath('appData'), 'autostart'); const autostartFilePath = path.join(autostartDir, DESKTOP_FILE_NAME); if (openAtLogin) { @@ -48,7 +48,7 @@ export async function setOpenAtLogin(openAtLogin: boolean) { log.error(`Failed to set auto-start: ${error.message}`); } } else { - remote.app.setLoginItemSettings({ openAtLogin }); + app.setLoginItemSettings({ openAtLogin }); } } diff --git a/gui/packages/desktop/src/main/index.js b/gui/packages/desktop/src/main/index.js index d63a65a944..d1598c3210 100644 --- a/gui/packages/desktop/src/main/index.js +++ b/gui/packages/desktop/src/main/index.js @@ -8,6 +8,7 @@ import mkdirp from 'mkdirp'; import uuid from 'uuid'; import { app, screen, BrowserWindow, ipcMain, Tray, Menu, nativeImage } from 'electron'; +import { getOpenAtLogin, setOpenAtLogin } from './autostart'; import NotificationController from './notification-controller'; import WindowController from './window-controller'; @@ -298,6 +299,10 @@ const ApplicationMain = { } } + if (newState.autoConnect !== oldState.autoConnect) { + this._updateDaemonsAutoConnect(); + } + if (this._windowController) { IpcMainEventChannel.guiSettings.notify(this._windowController.webContents, newState); } @@ -751,6 +756,7 @@ const ApplicationMain = { IpcMainEventChannel.state.handleGet(() => ({ isConnected: this._connectedToDaemon, + autoStart: getOpenAtLogin(), tunnelState: this._tunnelState, settings: this._settings, location: this._location, @@ -760,6 +766,10 @@ const ApplicationMain = { guiSettings: this._guiSettings.state, })); + IpcMainEventChannel.autoStart.handleSet((autoStart: boolean) => { + return this._setAutoStart(autoStart); + }); + IpcMainEventChannel.guiSettings.handleAutoConnect((autoConnect: boolean) => { this._guiSettings.autoConnect = autoConnect; }); @@ -854,6 +864,30 @@ const ApplicationMain = { ); }, + _updateDaemonsAutoConnect() { + const daemonAutoConnect = this._guiSettings.autoConnect && getOpenAtLogin(); + if (daemonAutoConnect !== this._settings.autoConnect) { + this._daemonRpc.setAutoConnect(daemonAutoConnect); + } + }, + + async _setAutoStart(autoStart: boolean): Promise<void> { + try { + await setOpenAtLogin(autoStart); + + if (this._windowController) { + IpcMainEventChannel.autoStart.notify(this._windowController.webContents, autoStart); + } + + this._updateDaemonsAutoConnect(); + } catch (error) { + log.error( + `Failed to update the autostart to ${autoStart.toString()}. ${error.message.toString()}`, + ); + } + return Promise.resolve(); + }, + async _installDevTools() { const installer = require('electron-devtools-installer'); const extensions = ['REACT_DEVELOPER_TOOLS', 'REDUX_DEVTOOLS']; diff --git a/gui/packages/desktop/src/renderer/app.js b/gui/packages/desktop/src/renderer/app.js index f433688a98..1506b5fa9b 100644 --- a/gui/packages/desktop/src/renderer/app.js +++ b/gui/packages/desktop/src/renderer/app.js @@ -14,7 +14,6 @@ import { createMemoryHistory } from 'history'; import { InvalidAccountError } from '../main/errors'; import makeRoutes from './routes'; -import { getOpenAtLogin, setOpenAtLogin } from './lib/autostart'; import configureStore from './redux/store'; import accountActions from './redux/account/actions'; @@ -58,6 +57,7 @@ export default class AppRenderer { _tunnelState: TunnelStateTransition; _settings: Settings; + _guiSettings: GuiSettingsState; _connectedToDaemon = false; _autoConnected = false; _doingLogin = false; @@ -131,6 +131,10 @@ export default class AppRenderer { this._setGuiSettings(guiSettings); }); + IpcRendererEventChannel.autoStart.listen((autoStart: boolean) => { + this._setAutoStart(autoStart); + }); + // Request the initial state from the main process const initialState = IpcRendererEventChannel.state.get(); @@ -145,6 +149,7 @@ export default class AppRenderer { this._setCurrentVersion(initialState.currentVersion); this._setUpgradeVersion(initialState.upgradeVersion); this._setGuiSettings(initialState.guiSettings); + this._setAutoStart(initialState.autoStart); if (initialState.isConnected) { this._onDaemonConnected(); @@ -331,27 +336,15 @@ export default class AppRenderer { } async setAutoConnect(autoConnect: boolean) { - const actions = this._reduxActions; - await IpcRendererEventChannel.guiSettings.setAutoConnect(autoConnect); - await this._setDaemonAutoConnect(autoConnect, getOpenAtLogin()); - actions.settings.updateAutoConnect(autoConnect); - } + this._reduxActions.settings.updateAutoConnect(autoConnect); - _getAutoConnect(): boolean { - return this._reduxStore.getState().settings.guiSettings.autoConnect; + return IpcRendererEventChannel.guiSettings.setAutoConnect(autoConnect); } - async setAutoStart(autoStart: boolean) { - await setOpenAtLogin(autoStart); - await this._setDaemonAutoConnect(this._getAutoConnect(), autoStart); - } + async setAutoStart(autoStart: boolean): Promise<void> { + this._setAutoStart(autoStart); - async _setDaemonAutoConnect(guiAutoConnect: boolean, autoStart: boolean) { - const daemonAutoConnect = guiAutoConnect && autoStart; - - if (daemonAutoConnect !== this._settings.autoConnect) { - await this._daemonRpc.setAutoConnect(daemonAutoConnect); - } + return IpcRendererEventChannel.autoStart.set(autoStart); } setStartMinimized(startMinimized: boolean) { @@ -400,7 +393,7 @@ export default class AppRenderer { } else if (this._autoConnected) { log.debug('Skip autoconnect because it was done before'); } else if (this._settings.accountToken) { - if (this._getAutoConnect()) { + if (this._guiSettings.autoConnect) { try { log.debug('Autoconnect the tunnel'); @@ -526,8 +519,13 @@ export default class AppRenderer { } _setGuiSettings(guiSettings: GuiSettingsState) { + this._guiSettings = guiSettings; this._reduxActions.settings.updateGuiSettings(guiSettings); } + + _setAutoStart(autoStart: boolean) { + this._reduxActions.settings.updateAutoStart(autoStart); + } } type AccountVerification = { status: 'verified' } | { status: 'deferred', error: Error }; diff --git a/gui/packages/desktop/src/renderer/components/Preferences.js b/gui/packages/desktop/src/renderer/components/Preferences.js index b7191804ed..b5b8405b75 100644 --- a/gui/packages/desktop/src/renderer/components/Preferences.js +++ b/gui/packages/desktop/src/renderer/components/Preferences.js @@ -16,13 +16,13 @@ import Switch from './Switch'; import styles from './PreferencesStyles'; export type PreferencesProps = { + autoStart: boolean, autoConnect: boolean, allowLan: boolean, monochromaticIcon: boolean, startMinimized: boolean, enableMonochromaticIconToggle: boolean, enableStartMinimizedToggle: boolean, - getAutoStart: () => boolean, setAutoStart: (boolean) => void, setAutoConnect: (boolean) => void, setAllowLan: (boolean) => void, @@ -31,20 +31,7 @@ export type PreferencesProps = { onClose: () => void, }; -type State = { - autoStart: boolean, -}; - -export default class Preferences extends Component<PreferencesProps, State> { - state = { - autoStart: false, - }; - - constructor(props: PreferencesProps) { - super(); - this.state.autoStart = props.getAutoStart(); - } - +export default class Preferences extends Component<PreferencesProps> { render() { return ( <Layout> @@ -65,7 +52,7 @@ export default class Preferences extends Component<PreferencesProps, State> { <View style={styles.preferences__content}> <Cell.Container> <Cell.Label>Launch app on start-up</Cell.Label> - <Switch isOn={this.state.autoStart} onChange={this._onChangeAutoStart} /> + <Switch isOn={this.props.autoStart} onChange={this._onChangeAutoStart} /> </Cell.Container> <View style={styles.preferences__separator} /> @@ -108,8 +95,6 @@ export default class Preferences extends Component<PreferencesProps, State> { _onChangeAutoStart = (autoStart: boolean) => { this.props.setAutoStart(autoStart); - // TODO: Handle failure to set auto-start - this.setState({ autoStart }); }; } diff --git a/gui/packages/desktop/src/renderer/containers/PreferencesPage.js b/gui/packages/desktop/src/renderer/containers/PreferencesPage.js index 565160c528..0d18e50bee 100644 --- a/gui/packages/desktop/src/renderer/containers/PreferencesPage.js +++ b/gui/packages/desktop/src/renderer/containers/PreferencesPage.js @@ -5,12 +5,12 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { goBack } from 'connected-react-router'; import Preferences from '../components/Preferences'; -import { getOpenAtLogin } from '../lib/autostart'; import type { ReduxState, ReduxDispatch } from '../redux/store'; import type { SharedRouteProps } from '../routes'; const mapStateToProps = (state: ReduxState) => ({ + autoStart: state.settings.autoStart, autoConnect: state.settings.guiSettings.autoConnect, allowLan: state.settings.allowLan, monochromaticIcon: state.settings.guiSettings.monochromaticIcon, @@ -23,9 +23,6 @@ const mapDispatchToProps = (dispatch: ReduxDispatch, props: SharedRouteProps) => onClose: () => { history.goBack(); }, - getAutoStart: () => { - return getOpenAtLogin(); - }, setAutoStart: async (autoStart) => { try { await props.app.setAutoStart(autoStart); diff --git a/gui/packages/desktop/src/renderer/lib/daemon-rpc-proxy.js b/gui/packages/desktop/src/renderer/lib/daemon-rpc-proxy.js index 182fb0fbb2..45a4abe89c 100644 --- a/gui/packages/desktop/src/renderer/lib/daemon-rpc-proxy.js +++ b/gui/packages/desktop/src/renderer/lib/daemon-rpc-proxy.js @@ -130,8 +130,8 @@ export default class DaemonRpcProxy implements DaemonRpcProtocol { return this._sendMessage('setOpenVpnMssfix', mssfix); } - setAutoConnect(autoConnect: boolean): Promise<void> { - return this._sendMessage('setAutoConnect', autoConnect); + setAutoConnect(_autoConnect: boolean): Promise<void> { + throw new Error('Do not call this method.'); } connectTunnel(): Promise<void> { diff --git a/gui/packages/desktop/src/renderer/redux/settings/actions.js b/gui/packages/desktop/src/renderer/redux/settings/actions.js index ff6e8a0e3d..20b185c8b3 100644 --- a/gui/packages/desktop/src/renderer/redux/settings/actions.js +++ b/gui/packages/desktop/src/renderer/redux/settings/actions.js @@ -43,6 +43,11 @@ export type UpdateOpenVpnMssfixAction = { mssfix: ?number, }; +export type UpdateAutoStartAction = { + type: 'UPDATE_AUTO_START', + autoStart: boolean, +}; + export type SettingsAction = | UpdateGuiSettingsAction | UpdateRelayAction @@ -51,7 +56,8 @@ export type SettingsAction = | UpdateAllowLanAction | UpdateEnableIpv6Action | UpdateBlockWhenDisconnectedAction - | UpdateOpenVpnMssfixAction; + | UpdateOpenVpnMssfixAction + | UpdateAutoStartAction; function updateGuiSettings(guiSettings: GuiSettingsState): UpdateGuiSettingsAction { return { @@ -113,6 +119,13 @@ function updateOpenVpnMssfix(mssfix: ?number): UpdateOpenVpnMssfixAction { }; } +function updateAutoStart(autoStart: boolean): UpdateAutoStartAction { + return { + type: 'UPDATE_AUTO_START', + autoStart, + }; +} + export default { updateGuiSettings, updateRelay, @@ -122,4 +135,5 @@ export default { updateEnableIpv6, updateBlockWhenDisconnected, updateOpenVpnMssfix, + updateAutoStart, }; diff --git a/gui/packages/desktop/src/renderer/redux/settings/reducers.js b/gui/packages/desktop/src/renderer/redux/settings/reducers.js index 7f5d1c42ef..b92a72d7d0 100644 --- a/gui/packages/desktop/src/renderer/redux/settings/reducers.js +++ b/gui/packages/desktop/src/renderer/redux/settings/reducers.js @@ -45,6 +45,7 @@ export type RelayLocationRedux = { }; export type SettingsReduxState = { + autoStart: boolean, guiSettings: GuiSettingsState, relaySettings: RelaySettingsRedux, relayLocations: Array<RelayLocationRedux>, @@ -57,6 +58,7 @@ export type SettingsReduxState = { }; const initialState: SettingsReduxState = { + autoStart: false, guiSettings: { autoConnect: true, monochromaticIcon: false, @@ -134,6 +136,12 @@ export default function( }, }; + case 'UPDATE_AUTO_START': + return { + ...state, + autoStart: action.autoStart, + }; + default: return state; } diff --git a/gui/packages/desktop/src/shared/ipc-event-channel.js b/gui/packages/desktop/src/shared/ipc-event-channel.js index 029ff7dd26..273a543790 100644 --- a/gui/packages/desktop/src/shared/ipc-event-channel.js +++ b/gui/packages/desktop/src/shared/ipc-event-channel.js @@ -17,6 +17,7 @@ import type { export type AppStateSnapshot = { isConnected: boolean, + autoStart: boolean, tunnelState: TunnelStateTransition, settings: Settings, location: ?Location, @@ -66,6 +67,15 @@ interface AccountHistoryMethods { removeItem(token: AccountToken): Promise<void>; } +interface AutoStartMethods { + listen(fn: (boolean) => void): void; + set(autoStart: boolean): Promise<void>; +} + +interface AutoStartHandlers { + handleSet: ((boolean) => Promise<void>) => void; +} + /// Events names const DAEMON_CONNECTED = 'daemon-connected'; @@ -76,17 +86,23 @@ const LOCATION_CHANGED = 'location-changed'; const RELAYS_CHANGED = 'relays-changed'; const CURRENT_VERSION_CHANGED = 'current-version-changed'; const UPGRADE_VERSION_CHANGED = 'upgrade-version-changed'; -const GUI_SETTINGS_CHANGED = 'gui-settings-changed'; +const GUI_SETTINGS_CHANGED = 'gui-settings-changed'; const SET_AUTO_CONNECT = 'set-auto-connect'; const SET_MONOCHROMATIC_ICON = 'set-monochromatic-icon'; const SET_START_MINIMIZED = 'set-start-minimized'; + const GET_APP_STATE = 'get-app-state'; + const GET_ACCOUNT_HISTORY = 'get-account-history'; const REMOVE_ACCOUNT_HISTORY_ITEM = 'remove-account-history-item'; + const SET_ACCOUNT = 'set-account'; const UNSET_ACCOUNT = 'unset-account'; +const AUTO_START_CHANGED = 'auto-start-changed'; +const SET_AUTO_START = 'set-auto-start'; + /// Typed IPC event channel /// /// Static methods are meant to be provide the way to send the events from a renderer process, while @@ -139,6 +155,11 @@ export class IpcRendererEventChannel { setStartMinimized: set(SET_START_MINIMIZED), }; + static autoStart: Receiver<boolean> & AutoStartMethods = { + listen: listen(AUTO_START_CHANGED), + set: requestSender(SET_AUTO_START), + }; + static account: AccountMethods = { set: requestSender(SET_ACCOUNT), unset: requestSender(UNSET_ACCOUNT), @@ -198,6 +219,11 @@ export class IpcMainEventChannel { handleStartMinimized: handler(SET_START_MINIMIZED), }; + static autoStart: Sender<boolean> & AutoStartHandlers = { + notify: sender(AUTO_START_CHANGED), + handleSet: requestHandler(SET_AUTO_START), + }; + static account: AccountHandlers = { handleSet: requestHandler(SET_ACCOUNT), handleUnset: requestHandler(UNSET_ACCOUNT), |
