diff --git a/desktop/packages/mullvad-vpn/src/main/index.ts b/desktop/packages/mullvad-vpn/src/main/index.ts index 57984b6092de..2297781f44d1 100644 --- a/desktop/packages/mullvad-vpn/src/main/index.ts +++ b/desktop/packages/mullvad-vpn/src/main/index.ts @@ -14,6 +14,7 @@ import { AccessMethodSetting, DaemonEvent, DeviceEvent, + ErrorStateCause, IRelayListWithEndpointData, ISettings, TunnelState, @@ -130,6 +131,10 @@ class ApplicationMain private currentApiAccessMethod?: AccessMethodSetting; + // If set to true, the GUI should restart the daemon when it exits. + // This is to make sure that the daemon is granted full-disk access. + private needFullDiskAccess = false; + public constructor() { this.daemonRpc = new DaemonRpc( new ConnectionObserver(this.onDaemonConnected, this.onDaemonDisconnected), @@ -324,7 +329,7 @@ class ApplicationMain }; private onBeforeQuit = async (event: Electron.Event) => { - if (this.tunnelState.needFullDiskAccess) { + if (this.needFullDiskAccess) { await this.daemonRpc.prepareRestart(true); } @@ -537,7 +542,7 @@ class ApplicationMain // fetch the tunnel state try { - this.tunnelState.handleNewTunnelState(await this.daemonRpc.getState()); + this.handleNewTunnelState(await this.daemonRpc.getState()); } catch (e) { const error = e as Error; log.error(`Failed to fetch the tunnel state: ${error.message}`); @@ -692,7 +697,7 @@ class ApplicationMain const daemonEventListener = new SubscriptionListener( (daemonEvent: DaemonEvent) => { if ('tunnelState' in daemonEvent) { - this.tunnelState.handleNewTunnelState(daemonEvent.tunnelState); + this.handleNewTunnelState(daemonEvent.tunnelState); } else if ('settings' in daemonEvent) { this.setSettings(daemonEvent.settings); } else if ('relayList' in daemonEvent) { @@ -738,6 +743,16 @@ class ApplicationMain void this.updateSplitTunnelingApplications(newSettings.splitTunnel.appsList); } + private async handleNewTunnelState(newState: TunnelState) { + this.tunnelState.handleNewTunnelState(await this.daemonRpc.getState()); + if ( + newState.state === 'error' && + newState.details?.cause === ErrorStateCause.needFullDiskPermissions + ) { + this.needFullDiskAccess = true; + } + } + private setRelayList(relayList: IRelayListWithEndpointData) { this.relayList = relayList; IpcMainEventChannel.relays.notify?.(relayList); @@ -834,7 +849,7 @@ class ApplicationMain }); IpcMainEventChannel.macOsSplitTunneling.handleNeedFullDiskPermissions(async () => { const fullDiskState = await this.daemonRpc.needFullDiskPermissions(); - this.tunnelState.needFullDiskAccess = fullDiskState; + this.needFullDiskAccess = fullDiskState; return fullDiskState; }); diff --git a/desktop/packages/mullvad-vpn/src/main/tunnel-state.ts b/desktop/packages/mullvad-vpn/src/main/tunnel-state.ts index b83b88a0f8ba..41305ac582ac 100644 --- a/desktop/packages/mullvad-vpn/src/main/tunnel-state.ts +++ b/desktop/packages/mullvad-vpn/src/main/tunnel-state.ts @@ -1,5 +1,5 @@ import { connectEnabled, disconnectEnabled, reconnectEnabled } from '../shared/connect-helper'; -import { ErrorStateCause, ILocation, TunnelState } from '../shared/daemon-rpc-types'; +import { ILocation, TunnelState } from '../shared/daemon-rpc-types'; import { Scheduler } from '../shared/scheduler'; export interface TunnelStateProvider { @@ -11,8 +11,6 @@ export interface TunnelStateHandlerDelegate { } export default class TunnelStateHandler { - public needFullDiskAccess = false; - // The current tunnel state private tunnelStateValue: TunnelState = { state: 'disconnected' }; // When pressing connect/disconnect/reconnect the app assumes what the next state will be before @@ -55,12 +53,6 @@ export default class TunnelStateHandler { } public handleNewTunnelState(newState: TunnelState) { - if (newState.state === 'error' && newState.details) { - if (newState.details.cause === ErrorStateCause.needFullDiskPermissions) { - this.needFullDiskAccess = true; - } - } - // If there's a fallback state set then the app is in an assumed next state and need to check // if it's now reached or if the current state should be ignored and set as the fallback state. if (this.tunnelStateFallback) {