diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2018-07-27 13:18:47 -0300 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2018-07-27 13:18:47 -0300 |
| commit | 0f0bd402988c91951d004a3c4ee802faf52d504f (patch) | |
| tree | 366c63262868212b925fbae64613c27b9b19aca5 | |
| parent | d120021305aeb01ce106e3c1e8a53a5295424ccb (diff) | |
| parent | 8b55f0f1246b4a89f55e66e4ad92865364448794 (diff) | |
| download | mullvadvpn-0f0bd402988c91951d004a3c4ee802faf52d504f.tar.xz mullvadvpn-0f0bd402988c91951d004a3c4ee802faf52d504f.zip | |
Merge branch 'linux-autostart'
| -rw-r--r-- | app/components/Preferences.js | 1 | ||||
| -rw-r--r-- | app/lib/platform.js | 93 |
2 files changed, 79 insertions, 15 deletions
diff --git a/app/components/Preferences.js b/app/components/Preferences.js index ceb76f4384..3fe803a156 100644 --- a/app/components/Preferences.js +++ b/app/components/Preferences.js @@ -99,6 +99,7 @@ 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/app/lib/platform.js b/app/lib/platform.js index 0e46341149..2ba438274f 100644 --- a/app/lib/platform.js +++ b/app/lib/platform.js @@ -1,10 +1,18 @@ // @flow +import fs from 'fs'; import { remote, shell } from 'electron'; import electronLog from 'electron-log'; import { execFile } from 'child_process'; +import path from 'path'; import { promisify } from 'util'; +const DESKTOP_FILE_NAME = 'mullvad-vpn.desktop'; + const execFileAsync = promisify(execFile); +const mkdirAsync = promisify(fs.mkdir); +const statAsync = promisify(fs.stat); +const symlinkAsync = promisify(fs.symlink); +const unlinkAsync = promisify(fs.unlink); const log = electronLog; @@ -12,33 +20,88 @@ const getAppVersion = () => { return remote.app.getVersion(); }; -const getOpenAtLogin = () => { - return remote.app.getLoginItemSettings().openAtLogin; +const getOpenAtLogin = (): boolean => { + if (process.platform === 'linux') { + try { + const autostartDir = path.join(remote.app.getPath('appData'), 'autostart'); + const autostartFilePath = path.join(autostartDir, DESKTOP_FILE_NAME); + + fs.accessSync(autostartFilePath); + + return true; + } catch (error) { + log.debug(`Failed to check autostart file: ${error.message}`); + return false; + } + } else { + return remote.app.getLoginItemSettings().openAtLogin; + } }; const setOpenAtLogin = async (openAtLogin: boolean) => { // setLoginItemSettings is broken on macOS and cannot delete login items. // Issue: https://github.com/electron/electron/issues/10880 - if (process.platform === 'darwin' && openAtLogin === false) { - // process.execPath in renderer process points to the sub-bundle of Electron Helper. - // This regular expression extracts the path to the app bundle, which is the first occurrence of - // file with .app extension. - const matches = process.execPath.match(/([a-z0-9 ]+)\.app/i); - if (matches && matches.length > 1) { - const bundleName = matches[1]; - const appleScript = `on run argv - set itemName to item 1 of argv - tell application "System Events" to delete login item itemName - end run`; - await execFileAsync('osascript', ['-e', appleScript, bundleName]); + if (process.platform === 'darwin') { + if (openAtLogin === false) { + // process.execPath in renderer process points to the sub-bundle of Electron Helper. + // This regular expression extracts the path to the app bundle, which is the first occurrence of + // file with .app extension. + const matches = process.execPath.match(/([a-z0-9 ]+)\.app/i); + if (matches && matches.length > 1) { + const bundleName = matches[1]; + const appleScript = `on run argv + set itemName to item 1 of argv + tell application "System Events" to delete login item itemName + end run`; + await execFileAsync('osascript', ['-e', appleScript, bundleName]); + } else { + log.error(`Cannot extract the app bundle name from ${process.execPath}`); + } } else { - log.error(`Cannot extract the app bundle name from ${process.execPath}`); + remote.app.setLoginItemSettings({ openAtLogin }); + } + } else 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 autostartFilePath = path.join(autostartDir, DESKTOP_FILE_NAME); + + if (openAtLogin) { + await createDirIfNecessary(autostartDir); + await symlinkAsync(desktopFilePath, autostartFilePath); + } else { + await unlinkAsync(autostartFilePath); + } + } catch (error) { + log.error(`Failed to set auto-start: ${error.message}`); } } else { remote.app.setLoginItemSettings({ openAtLogin }); } }; +const createDirIfNecessary = async (directory: string) => { + let stat; + try { + stat = await statAsync(directory); + } catch (error) { + // Path doesn't exist, so it has to be created + return mkdirAsync(directory); + } + + // Is there a file instead of a directory? + if (!stat.isDirectory()) { + // Try to remove existing file and replace it with a new directory + try { + await unlinkAsync(directory); + } catch (error) { + log.debug(`Failed to remove path before creating a directory for it: ${error.message}`); + } + + return mkdirAsync(directory); + } +}; + const exit = () => { remote.app.quit(); }; |
