summaryrefslogtreecommitdiffhomepage
path: root/desktop
diff options
context:
space:
mode:
authorOliver <oliver@mohlin.dev>2025-06-17 14:09:38 +0200
committerOskar <oskar@mullvad.net>2025-06-30 11:05:27 +0200
commitf1ae892a9edbfb8ecc3a84f21332082dac113ea3 (patch)
tree32b6c3d4a4524894411eb1220446b3d8545f719f /desktop
parentced6456945c038b05e7222c13001488eb323d422 (diff)
downloadmullvadvpn-f1ae892a9edbfb8ecc3a84f21332082dac113ea3.tar.xz
mullvadvpn-f1ae892a9edbfb8ecc3a84f21332082dac113ea3.zip
Implement daemon status management and related IPC communication
Diffstat (limited to 'desktop')
-rw-r--r--desktop/packages/mullvad-vpn/src/main/user-interface.ts15
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/app.tsx20
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/actions.ts16
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/hooks/index.ts1
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/hooks/useUserInterfaceDaemonStatus.ts7
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/reducers.ts9
-rw-r--r--desktop/packages/mullvad-vpn/src/shared/ipc-schema.ts3
-rw-r--r--desktop/packages/mullvad-vpn/src/shared/ipc-types.ts2
8 files changed, 69 insertions, 4 deletions
diff --git a/desktop/packages/mullvad-vpn/src/main/user-interface.ts b/desktop/packages/mullvad-vpn/src/main/user-interface.ts
index 0c295aad77..50b152601f 100644
--- a/desktop/packages/mullvad-vpn/src/main/user-interface.ts
+++ b/desktop/packages/mullvad-vpn/src/main/user-interface.ts
@@ -1,4 +1,4 @@
-import { exec } from 'child_process';
+import { exec, spawn } from 'child_process';
import { app, BrowserWindow, dialog, Menu, nativeImage, screen, Tray } from 'electron';
import path from 'path';
import { sprintf } from 'sprintf-js';
@@ -62,6 +62,19 @@ export default class UserInterface implements WindowControllerDelegate {
}
public registerIpcListeners() {
+ IpcMainEventChannel.daemon.handleTryStart(() => {
+ const child = spawn('cmd.exe', {
+ detached: true,
+ stdio: 'ignore',
+ windowsVerbatimArguments: true,
+ });
+
+ child.once('error', (error) => {
+ log.error(`Could not start daemon: ${error.message}`);
+ IpcMainEventChannel.daemon.notifyTryStartEvent?.('stopped');
+ });
+ });
+
IpcMainEventChannel.app.handleShowOpenDialog(async (options) => {
this.browsingFiles = true;
const response = await dialog.showOpenDialog({
diff --git a/desktop/packages/mullvad-vpn/src/renderer/app.tsx b/desktop/packages/mullvad-vpn/src/renderer/app.tsx
index 8c39327f40..4658fe8b61 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/app.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/app.tsx
@@ -36,7 +36,12 @@ import {
} from '../shared/daemon-rpc-types';
import { messages, relayLocations } from '../shared/gettext';
import { IGuiSettingsState, SYSTEM_PREFERRED_LOCALE_KEY } from '../shared/gui-settings-state';
-import { IChangelog, ICurrentAppVersionInfo, IHistoryObject } from '../shared/ipc-types';
+import {
+ DaemonStatus,
+ IChangelog,
+ ICurrentAppVersionInfo,
+ IHistoryObject,
+} from '../shared/ipc-types';
import log, { ConsoleOutput } from '../shared/logging';
import { LogLevel } from '../shared/logging-types';
import { RoutePath } from '../shared/routes';
@@ -176,6 +181,10 @@ export default class AppRenderer {
this.setRelayListPair(relayListPair);
});
+ IpcRendererEventChannel.daemon.listenTryStartEvent((status: DaemonStatus) => {
+ this.reduxActions.userInterface.setDaemonStatus(status);
+ });
+
IpcRendererEventChannel.app.listenUpgradeEvent((appUpgradeEvent) => {
this.reduxActions.appUpgrade.setAppUpgradeEvent(appUpgradeEvent);
@@ -436,6 +445,13 @@ export default class AppRenderer {
public daemonPrepareRestart = (shutdown: boolean): void => {
IpcRendererEventChannel.daemon.prepareRestart(shutdown);
};
+
+ public tryStartDaemon = () => {
+ this.reduxActions.userInterface.setDaemonStatus('start-requested');
+ if (window.env.platform === 'win32') IpcRendererEventChannel.daemon.tryStart();
+ else this.reduxActions.userInterface.setDaemonStatus('stopped');
+ };
+
public appUpgrade = () => {
const reduxState = this.reduxStore.getState();
const appUpgradeError = reduxState.appUpgrade.error;
@@ -804,12 +820,14 @@ export default class AppRenderer {
this.connectedToDaemon = true;
this.reduxActions.userInterface.setConnectedToDaemon(true);
this.reduxActions.userInterface.setDaemonAllowed(true);
+ this.reduxActions.userInterface.setDaemonStatus('running');
this.resetNavigation();
}
private onDaemonDisconnected() {
this.connectedToDaemon = false;
this.reduxActions.userInterface.setConnectedToDaemon(false);
+ this.reduxActions.userInterface.setDaemonStatus('stopped');
this.resetNavigation();
}
diff --git a/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/actions.ts b/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/actions.ts
index 83c0252452..00764e1375 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/actions.ts
+++ b/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/actions.ts
@@ -1,5 +1,5 @@
import { MacOsScrollbarVisibility } from '../../../shared/ipc-schema';
-import { IChangelog } from '../../../shared/ipc-types';
+import { DaemonStatus, IChangelog } from '../../../shared/ipc-types';
import { LocationType } from '../../components/select-location/select-location-types';
export interface IUpdateLocaleAction {
@@ -31,6 +31,11 @@ export interface ISetConnectedToDaemon {
connectedToDaemon: boolean;
}
+export interface ISetDaemonStatus {
+ type: 'SET_DAEMON_STATUS';
+ daemonStatus: DaemonStatus;
+}
+
export interface ISetDaemonAllowed {
type: 'SET_DAEMON_ALLOWED';
daemonAllowed: boolean;
@@ -63,6 +68,7 @@ export type UserInterfaceAction =
| ISetWindowFocusedAction
| ISetMacOsScrollbarVisibility
| ISetConnectedToDaemon
+ | ISetDaemonStatus
| ISetDaemonAllowed
| ISetChangelog
| ISetIsPerformingPostUpgrade
@@ -112,6 +118,13 @@ function setConnectedToDaemon(connectedToDaemon: boolean): ISetConnectedToDaemon
};
}
+function setDaemonStatus(daemonStatus: DaemonStatus): ISetDaemonStatus {
+ return {
+ type: 'SET_DAEMON_STATUS',
+ daemonStatus: daemonStatus,
+ };
+}
+
function setDaemonAllowed(daemonAllowed: boolean): ISetDaemonAllowed {
return {
type: 'SET_DAEMON_ALLOWED',
@@ -154,6 +167,7 @@ export default {
setWindowFocused,
setMacOsScrollbarVisibility,
setConnectedToDaemon,
+ setDaemonStatus,
setDaemonAllowed,
setChangelog,
setIsPerformingPostUpgrade,
diff --git a/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/hooks/index.ts b/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/hooks/index.ts
index 0b7ee7ff2a..528eae8cfe 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/hooks/index.ts
+++ b/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/hooks/index.ts
@@ -1,3 +1,4 @@
export * from './useUserInterfaceChangelog';
export * from './useUserInterfaceConnectedToDaemon';
+export * from './useUserInterfaceDaemonStatus';
export * from './useUserInterfaceIsMacOs13OrNewer';
diff --git a/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/hooks/useUserInterfaceDaemonStatus.ts b/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/hooks/useUserInterfaceDaemonStatus.ts
new file mode 100644
index 0000000000..1a9424d771
--- /dev/null
+++ b/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/hooks/useUserInterfaceDaemonStatus.ts
@@ -0,0 +1,7 @@
+import { useSelector } from '../../store';
+
+export const useUserInterfaceDaemonStatus = () => {
+ return {
+ daemonStatus: useSelector((state) => state.userInterface.daemonStatus),
+ };
+};
diff --git a/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/reducers.ts b/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/reducers.ts
index 46bdfc6308..e1bbe6e0dd 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/reducers.ts
+++ b/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/reducers.ts
@@ -1,5 +1,5 @@
import { MacOsScrollbarVisibility } from '../../../shared/ipc-schema';
-import { IChangelog } from '../../../shared/ipc-types';
+import { DaemonStatus, IChangelog } from '../../../shared/ipc-types';
import { LocationType } from '../../components/select-location/select-location-types';
import { ReduxAction } from '../store';
@@ -10,6 +10,7 @@ export interface IUserInterfaceReduxState {
windowFocused: boolean;
macOsScrollbarVisibility?: MacOsScrollbarVisibility;
connectedToDaemon: boolean;
+ daemonStatus?: DaemonStatus;
daemonAllowed?: boolean;
changelog: IChangelog;
isPerformingPostUpgrade: boolean;
@@ -53,6 +54,12 @@ export default function (
case 'SET_CONNECTED_TO_DAEMON':
return { ...state, connectedToDaemon: action.connectedToDaemon };
+ case 'SET_DAEMON_STATUS':
+ return {
+ ...state,
+ daemonStatus: action.daemonStatus,
+ };
+
case 'SET_DAEMON_ALLOWED':
return { ...state, daemonAllowed: action.daemonAllowed };
diff --git a/desktop/packages/mullvad-vpn/src/shared/ipc-schema.ts b/desktop/packages/mullvad-vpn/src/shared/ipc-schema.ts
index 031d1fc593..4f2c9da0fd 100644
--- a/desktop/packages/mullvad-vpn/src/shared/ipc-schema.ts
+++ b/desktop/packages/mullvad-vpn/src/shared/ipc-schema.ts
@@ -37,6 +37,7 @@ import { MapData } from '../renderer/lib/3dmap';
import { AppUpgradeError, AppUpgradeEvent } from './app-upgrade';
import { invoke, invokeSync, notifyRenderer, send } from './ipc-helpers';
import {
+ DaemonStatus,
IChangelog,
ICurrentAppVersionInfo,
IHistoryObject,
@@ -143,6 +144,8 @@ export const ipcSchema = {
connected: notifyRenderer<void>(),
disconnected: notifyRenderer<void>(),
prepareRestart: send<boolean>(),
+ tryStart: send<void>(),
+ tryStartEvent: notifyRenderer<DaemonStatus>(),
},
relays: {
'': notifyRenderer<IRelayListWithEndpointData>(),
diff --git a/desktop/packages/mullvad-vpn/src/shared/ipc-types.ts b/desktop/packages/mullvad-vpn/src/shared/ipc-types.ts
index 40a32e42fa..c3fe8ef2b0 100644
--- a/desktop/packages/mullvad-vpn/src/shared/ipc-types.ts
+++ b/desktop/packages/mullvad-vpn/src/shared/ipc-types.ts
@@ -35,3 +35,5 @@ export interface IHistoryObject {
}
export type ScrollPositions = Record<string, [number, number]>;
+
+export type DaemonStatus = 'start-requested' | 'running' | 'stopped';