diff options
| author | Tobias Järvelöv <tobias.jarvelov@mullvad.net> | 2025-05-19 16:12:42 +0200 |
|---|---|---|
| committer | Tobias Järvelöv <tobias.jarvelov@mullvad.net> | 2025-05-19 16:12:42 +0200 |
| commit | 7e136fb136b4bd72b5d134948c8442923680e91c (patch) | |
| tree | 2871cb6b77dfd865981b52745101c4a62863a001 | |
| parent | 2898ca982570d89415fd30e929b0ae7a0bcaab14 (diff) | |
| parent | 315160ab9d0f21ebd7b69177dc3d2203c501ce35 (diff) | |
| download | mullvadvpn-7e136fb136b4bd72b5d134948c8442923680e91c.tar.xz mullvadvpn-7e136fb136b4bd72b5d134948c8442923680e91c.zip | |
Merge branch 'update-electron-app-to-use-locked_down-field-in-des-549'
17 files changed, 59 insertions, 81 deletions
diff --git a/desktop/packages/mullvad-vpn/src/main/grpc-type-convertions.ts b/desktop/packages/mullvad-vpn/src/main/grpc-type-convertions.ts index 69549c1d3c..96334cc435 100644 --- a/desktop/packages/mullvad-vpn/src/main/grpc-type-convertions.ts +++ b/desktop/packages/mullvad-vpn/src/main/grpc-type-convertions.ts @@ -163,6 +163,7 @@ export function convertFromTunnelState( return { state: 'disconnected', location: tunnelStateObject.disconnected!.disconnectedLocation, + lockedDown: tunnelStateObject.disconnected!.lockedDown, }; case grpcTypes.TunnelState.StateCase.DISCONNECTING: { const detailsMap: Record<grpcTypes.AfterDisconnect, AfterDisconnect> = { diff --git a/desktop/packages/mullvad-vpn/src/main/index.ts b/desktop/packages/mullvad-vpn/src/main/index.ts index b2893b438b..57a0bf3dc9 100644 --- a/desktop/packages/mullvad-vpn/src/main/index.ts +++ b/desktop/packages/mullvad-vpn/src/main/index.ts @@ -431,16 +431,11 @@ class ApplicationMain this.tunnelStateExpectation = new Expectation(async () => { this.userInterface?.createTrayIconController( this.tunnelState.tunnelState, - this.settings.blockWhenDisconnected, this.settings.gui.monochromaticIcon, ); await this.userInterface?.updateTrayTheme(); - this.userInterface?.updateTray( - this.account.isLoggedIn(), - this.tunnelState.tunnelState, - this.settings.blockWhenDisconnected, - ); + this.userInterface?.updateTray(this.account.isLoggedIn(), this.tunnelState.tunnelState); if (process.platform === 'win32') { nativeTheme.on('updated', async () => { @@ -673,7 +668,10 @@ class ApplicationMain if (wasConnected) { // update the tray icon to indicate that the computer is not secure anymore - this.userInterface?.updateTray(false, { state: 'disconnected' }, false); + this.userInterface?.updateTray(false, { + state: 'disconnected', + lockedDown: this.settings.blockWhenDisconnected, + }); // notify renderer process IpcMainEventChannel.daemon.notifyDisconnected?.(); @@ -742,11 +740,7 @@ class ApplicationMain const oldSettings = this.settings; this.settings.handleNewSettings(newSettings); - this.userInterface?.updateTray( - this.account.isLoggedIn(), - this.tunnelState.tunnelState, - newSettings.blockWhenDisconnected, - ); + this.userInterface?.updateTray(this.account.isLoggedIn(), this.tunnelState.tunnelState); if (oldSettings.showBetaReleases !== newSettings.showBetaReleases) { this.version.setLatestVersion(this.version.upgradeVersion); @@ -949,11 +943,7 @@ class ApplicationMain relayLocations: relayLocationsTranslations, }; - this.userInterface?.updateTray( - this.account.isLoggedIn(), - this.tunnelState.tunnelState, - this.settings.blockWhenDisconnected, - ); + this.userInterface?.updateTray(this.account.isLoggedIn(), this.tunnelState.tunnelState); } private blockPermissionRequests() { @@ -1131,15 +1121,10 @@ class ApplicationMain // TunnelStateHandlerDelegate public handleTunnelStateUpdate = (tunnelState: TunnelState) => { - this.userInterface?.updateTray( - this.account.isLoggedIn(), - tunnelState, - this.settings.blockWhenDisconnected, - ); + this.userInterface?.updateTray(this.account.isLoggedIn(), tunnelState); this.notificationController.notifyTunnelState( tunnelState, - this.settings.blockWhenDisconnected, this.settings.splitTunnel.enableExclusions && this.settings.splitTunnel.appsList.length > 0, this.userInterface?.isWindowVisible() ?? false, this.settings.gui.enableSystemNotifications, @@ -1165,11 +1150,7 @@ class ApplicationMain public getLocale = () => this.locale; public getTunnelState = () => this.tunnelState.tunnelState; public onDeviceEvent = () => { - this.userInterface?.updateTray( - this.account.isLoggedIn(), - this.tunnelState.tunnelState, - this.settings.blockWhenDisconnected, - ); + this.userInterface?.updateTray(this.account.isLoggedIn(), this.tunnelState.tunnelState); if (this.isPerformingPostUpgrade) { void this.performPostUpgradeCheck(); diff --git a/desktop/packages/mullvad-vpn/src/main/notification-controller.ts b/desktop/packages/mullvad-vpn/src/main/notification-controller.ts index b21a9f2d27..b822911306 100644 --- a/desktop/packages/mullvad-vpn/src/main/notification-controller.ts +++ b/desktop/packages/mullvad-vpn/src/main/notification-controller.ts @@ -92,7 +92,6 @@ export default class NotificationController { public notifyTunnelState( tunnelState: TunnelState, - blockWhenDisconnected: boolean, hasExcludedApps: boolean, isWindowVisible: boolean, areSystemNotificationsEnabled: boolean, @@ -101,7 +100,7 @@ export default class NotificationController { new ConnectingNotificationProvider({ tunnelState, reconnecting: this.reconnecting }), new ConnectedNotificationProvider(tunnelState), new ReconnectingNotificationProvider(tunnelState), - new DisconnectedNotificationProvider({ tunnelState, blockWhenDisconnected }), + new DisconnectedNotificationProvider({ tunnelState }), new ErrorNotificationProvider({ tunnelState, hasExcludedApps }), ]; diff --git a/desktop/packages/mullvad-vpn/src/main/tunnel-state.ts b/desktop/packages/mullvad-vpn/src/main/tunnel-state.ts index 41305ac582..5ca3365136 100644 --- a/desktop/packages/mullvad-vpn/src/main/tunnel-state.ts +++ b/desktop/packages/mullvad-vpn/src/main/tunnel-state.ts @@ -12,7 +12,7 @@ export interface TunnelStateHandlerDelegate { export default class TunnelStateHandler { // The current tunnel state - private tunnelStateValue: TunnelState = { state: 'disconnected' }; + private tunnelStateValue: TunnelState = { state: 'disconnected', lockedDown: false }; // When pressing connect/disconnect/reconnect the app assumes what the next state will be before // it get's the new state from the daemon. The latest state from the daemon is saved as fallback // if the assumed state isn't reached. diff --git a/desktop/packages/mullvad-vpn/src/main/user-interface.ts b/desktop/packages/mullvad-vpn/src/main/user-interface.ts index 241135f707..b4779d5185 100644 --- a/desktop/packages/mullvad-vpn/src/main/user-interface.ts +++ b/desktop/packages/mullvad-vpn/src/main/user-interface.ts @@ -92,12 +92,8 @@ export default class UserInterface implements WindowControllerDelegate { }); } - public createTrayIconController( - tunnelState: TunnelState, - blockWhenDisconnected: boolean, - monochromaticIcon: boolean, - ) { - const iconType = this.trayIconType(tunnelState, blockWhenDisconnected); + public createTrayIconController(tunnelState: TunnelState, monochromaticIcon: boolean) { + const iconType = this.trayIconType(tunnelState); this.trayIconController = new TrayIconController(this.tray, iconType, monochromaticIcon, false); } @@ -163,12 +159,8 @@ export default class UserInterface implements WindowControllerDelegate { } } - public updateTray = ( - isLoggedIn: boolean, - tunnelState: TunnelState, - blockWhenDisconnected: boolean, - ) => { - this.updateTrayIcon(tunnelState, blockWhenDisconnected); + public updateTray = (isLoggedIn: boolean, tunnelState: TunnelState) => { + this.updateTrayIcon(tunnelState); this.setTrayContextMenu(isLoggedIn, tunnelState); this.setTrayTooltip(tunnelState); }; @@ -204,8 +196,8 @@ export default class UserInterface implements WindowControllerDelegate { this.trayIconController?.showNotificationIcon(value, reason); public setWindowIcon = (icon: string) => this.windowController.window?.setIcon(icon); - public updateTrayIcon(tunnelState: TunnelState, blockWhenDisconnected: boolean) { - const type = this.trayIconType(tunnelState, blockWhenDisconnected); + public updateTrayIcon(tunnelState: TunnelState) { + const type = this.trayIconType(tunnelState); this.trayIconController?.animateToIcon(type); } @@ -671,7 +663,7 @@ export default class UserInterface implements WindowControllerDelegate { return label.replace('&', '&&'); } - private trayIconType(tunnelState: TunnelState, blockWhenDisconnected: boolean): TrayIconType { + private trayIconType(tunnelState: TunnelState): TrayIconType { switch (tunnelState.state) { case 'connected': return 'secured'; @@ -689,7 +681,7 @@ export default class UserInterface implements WindowControllerDelegate { return 'securing'; case 'disconnected': - if (blockWhenDisconnected) { + if (tunnelState.lockedDown) { return 'securing'; } else { return 'unsecured'; diff --git a/desktop/packages/mullvad-vpn/src/renderer/app.tsx b/desktop/packages/mullvad-vpn/src/renderer/app.tsx index 114c1dd01e..5511fff941 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/app.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/app.tsx @@ -157,12 +157,12 @@ export default class AppRenderer { IpcRendererEventChannel.tunnel.listen((newState: TunnelState) => { this.setTunnelState(newState); - this.updateBlockedState(newState, this.settings.blockWhenDisconnected); + this.updateBlockedState(newState); }); IpcRendererEventChannel.settings.listen((newSettings: ISettings) => { this.setSettings(newSettings); - this.updateBlockedState(this.tunnelState, newSettings.blockWhenDisconnected); + this.updateBlockedState(this.tunnelState); }); IpcRendererEventChannel.settings.listenApiAccessMethodSettingChange((setting) => { @@ -237,7 +237,7 @@ export default class AppRenderer { this.setAccountHistory(initialState.accountHistory); this.setTunnelState(initialState.tunnelState); - this.updateBlockedState(initialState.tunnelState, initialState.settings.blockWhenDisconnected); + this.updateBlockedState(initialState.tunnelState); this.setRelayListPair(initialState.relayList); this.setCurrentVersion(initialState.currentVersion); @@ -803,7 +803,7 @@ export default class AppRenderer { break; case 'disconnected': - actions.connection.disconnected(); + actions.connection.disconnected(tunnelState.lockedDown); break; case 'error': @@ -847,7 +847,7 @@ export default class AppRenderer { this.reduxActions.userInterface.setIsPerformingPostUpgrade(isPerformingPostUpgrade); } - private updateBlockedState(tunnelState: TunnelState, blockWhenDisconnected: boolean) { + private updateBlockedState(tunnelState: TunnelState) { const actions = this.reduxActions.connection; switch (tunnelState.state) { case 'connecting': @@ -859,7 +859,7 @@ export default class AppRenderer { break; case 'disconnected': - actions.updateBlockState(blockWhenDisconnected); + actions.updateBlockState(tunnelState.lockedDown); break; case 'disconnecting': diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Login.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Login.tsx index 0e86ed9ac7..8662c669f9 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/Login.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/Login.tsx @@ -46,8 +46,9 @@ export default function LoginContainer() { const { accountNumber, accountHistory, status } = useSelector((state) => state.account); const tunnelState = useSelector((state) => state.connection.status); - const blockWhenDisconnected = useSelector((state) => state.settings.blockWhenDisconnected); - const showBlockMessage = tunnelState.state === 'error' || blockWhenDisconnected; + const showBlockMessage = + tunnelState.state === 'error' || + (tunnelState.state === 'disconnected' && tunnelState.lockedDown); const isPerformingPostUpgrade = useSelector( (state) => state.userInterface.isPerformingPostUpgrade, @@ -475,7 +476,7 @@ function AccountDropdownItem({ label, onRemove, onSelect, value }: AccountDropdo function BlockMessage() { const { setBlockWhenDisconnected, disconnectTunnel } = useAppContext(); const tunnelState = useSelector((state) => state.connection.status); - const blockWhenDisconnected = useSelector((state) => state.settings.blockWhenDisconnected); + const blockWhenDisconnected = tunnelState.state === 'disconnected' && tunnelState.lockedDown; const unlock = useCallback(() => { if (blockWhenDisconnected) { diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx index b22a533eab..4004d0cea9 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx @@ -59,7 +59,7 @@ export default function NotificationArea(props: IProps) { const allowedPortRanges = useSelector((state) => state.settings.wireguardEndpointData.portRanges); const relaySettings = useSelector((state) => state.settings.relaySettings); - const blockWhenDisconnected = useSelector( + const blockWhenDisconnectedSetting = useSelector( (state: IReduxState) => state.settings.blockWhenDisconnected, ); const hasExcludedApps = useSelector( @@ -94,7 +94,7 @@ export default function NotificationArea(props: IProps) { new ReconnectingNotificationProvider(tunnelState), new BlockWhenDisconnectedNotificationProvider({ tunnelState, - blockWhenDisconnected, + blockWhenDisconnectedSetting, hasExcludedApps, }), new NoOpenVpnServerAvailableNotificationProvider({ diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/main-view/ConnectionStatus.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/main-view/ConnectionStatus.tsx index a789ef8450..97c6e3a851 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/main-view/ConnectionStatus.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/main-view/ConnectionStatus.tsx @@ -14,9 +14,8 @@ const StyledConnectionStatus = styled.span<{ $color: string }>(largeText, (props export default function ConnectionStatus() { const tunnelState = useSelector((state) => state.connection.status); - const lockdownMode = useSelector((state) => state.settings.blockWhenDisconnected); - const color = getConnectionSTatusLabelColor(tunnelState, lockdownMode); + const color = getConnectionSTatusLabelColor(tunnelState); const text = getConnectionStatusLabelText(tunnelState); return ( @@ -26,7 +25,7 @@ export default function ConnectionStatus() { ); } -function getConnectionSTatusLabelColor(tunnelState: TunnelState, lockdownMode: boolean) { +function getConnectionSTatusLabelColor(tunnelState: TunnelState) { switch (tunnelState.state) { case 'connected': return colors.green; @@ -34,7 +33,7 @@ function getConnectionSTatusLabelColor(tunnelState: TunnelState, lockdownMode: b case 'disconnecting': return colors.white; case 'disconnected': - return lockdownMode ? colors.white : colors.red; + return tunnelState.lockedDown ? colors.white : colors.red; case 'error': return tunnelState.details.blockingError ? colors.red : colors.white; } diff --git a/desktop/packages/mullvad-vpn/src/renderer/redux/connection/actions.ts b/desktop/packages/mullvad-vpn/src/renderer/redux/connection/actions.ts index 8a3f98efe5..fdd350d602 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/redux/connection/actions.ts +++ b/desktop/packages/mullvad-vpn/src/renderer/redux/connection/actions.ts @@ -20,6 +20,7 @@ interface IConnectedAction { interface IDisconnectedAction { type: 'DISCONNECTED'; + lockedDown: boolean; } interface IDisconnectingAction { @@ -73,9 +74,10 @@ function connected( }; } -function disconnected(): IDisconnectedAction { +function disconnected(lockedDown: boolean): IDisconnectedAction { return { type: 'DISCONNECTED', + lockedDown: lockedDown, }; } diff --git a/desktop/packages/mullvad-vpn/src/renderer/redux/connection/reducers.ts b/desktop/packages/mullvad-vpn/src/renderer/redux/connection/reducers.ts index b597d29a64..4b293b3772 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/redux/connection/reducers.ts +++ b/desktop/packages/mullvad-vpn/src/renderer/redux/connection/reducers.ts @@ -16,7 +16,7 @@ export interface IConnectionReduxState { } const initialState: IConnectionReduxState = { - status: { state: 'disconnected' }, + status: { state: 'disconnected', lockedDown: true }, isBlocked: false, ipv4: undefined, ipv6: undefined, @@ -74,7 +74,7 @@ export default function ( case 'DISCONNECTED': return { ...state, - status: { state: 'disconnected' }, + status: { state: 'disconnected', lockedDown: action.lockedDown }, }; case 'DISCONNECTING': diff --git a/desktop/packages/mullvad-vpn/src/shared/daemon-rpc-types.ts b/desktop/packages/mullvad-vpn/src/shared/daemon-rpc-types.ts index ec9061e466..0d73280c4d 100644 --- a/desktop/packages/mullvad-vpn/src/shared/daemon-rpc-types.ts +++ b/desktop/packages/mullvad-vpn/src/shared/daemon-rpc-types.ts @@ -199,7 +199,11 @@ export enum FeatureIndicator { customMssFix, } -export type DisconnectedState = { state: 'disconnected'; location?: Partial<ILocation> }; +export type DisconnectedState = { + state: 'disconnected'; + location?: Partial<ILocation>; + lockedDown: boolean; +}; export type ConnectingState = { state: 'connecting'; details?: ITunnelStateRelayInfo; diff --git a/desktop/packages/mullvad-vpn/src/shared/notifications/block-when-disconnected.ts b/desktop/packages/mullvad-vpn/src/shared/notifications/block-when-disconnected.ts index 67ab96fb4a..6b8022c381 100644 --- a/desktop/packages/mullvad-vpn/src/shared/notifications/block-when-disconnected.ts +++ b/desktop/packages/mullvad-vpn/src/shared/notifications/block-when-disconnected.ts @@ -14,7 +14,7 @@ import { interface BlockWhenDisconnectedNotificationContext { tunnelState: TunnelState; - blockWhenDisconnected: boolean; + blockWhenDisconnectedSetting: boolean; hasExcludedApps: boolean; } @@ -25,9 +25,9 @@ export class BlockWhenDisconnectedNotificationProvider public mayDisplay() { return ( - (this.context.tunnelState.state === 'disconnecting' || - this.context.tunnelState.state === 'disconnected') && - this.context.blockWhenDisconnected + (this.context.tunnelState.state === 'disconnecting' && + this.context.blockWhenDisconnectedSetting) || + (this.context.tunnelState.state === 'disconnected' && this.context.tunnelState.lockedDown) ); } diff --git a/desktop/packages/mullvad-vpn/src/shared/notifications/disconnected.ts b/desktop/packages/mullvad-vpn/src/shared/notifications/disconnected.ts index 874cb11b3e..313b1ce8f2 100644 --- a/desktop/packages/mullvad-vpn/src/shared/notifications/disconnected.ts +++ b/desktop/packages/mullvad-vpn/src/shared/notifications/disconnected.ts @@ -9,14 +9,13 @@ import { interface DisconnectedNotificationContext { tunnelState: TunnelState; - blockWhenDisconnected: boolean; } export class DisconnectedNotificationProvider implements SystemNotificationProvider { public constructor(private context: DisconnectedNotificationContext) {} public mayDisplay = () => - this.context.tunnelState.state === 'disconnected' && !this.context.blockWhenDisconnected; + this.context.tunnelState.state === 'disconnected' && !this.context.tunnelState.lockedDown; public getSystemNotification(): SystemNotification | undefined { return { diff --git a/desktop/packages/mullvad-vpn/test/e2e/mocked/tunnel-state.spec.ts b/desktop/packages/mullvad-vpn/test/e2e/mocked/tunnel-state.spec.ts index 10df2b2654..f46ab3ce62 100644 --- a/desktop/packages/mullvad-vpn/test/e2e/mocked/tunnel-state.spec.ts +++ b/desktop/packages/mullvad-vpn/test/e2e/mocked/tunnel-state.spec.ts @@ -47,7 +47,7 @@ test('App should show disconnected tunnel state', async () => { }); await util.sendMockIpcResponse<TunnelState>({ channel: 'tunnel-', - response: { state: 'disconnected' }, + response: { state: 'disconnected', lockedDown: false }, }); await expectDisconnected(page); }); diff --git a/desktop/packages/mullvad-vpn/test/e2e/setup/main.ts b/desktop/packages/mullvad-vpn/test/e2e/setup/main.ts index 8fbd36ac39..700c71c5a5 100644 --- a/desktop/packages/mullvad-vpn/test/e2e/setup/main.ts +++ b/desktop/packages/mullvad-vpn/test/e2e/setup/main.ts @@ -154,7 +154,7 @@ class ApplicationMain { autoStart: false, accountData: this.accountData, accountHistory: undefined, - tunnelState: { state: 'disconnected', location: this.location }, + tunnelState: { state: 'disconnected', location: this.location, lockedDown: false }, settings: this.settings, isPerformingPostUpgrade: false, deviceState: this.deviceState, diff --git a/desktop/packages/mullvad-vpn/test/unit/notification-evaluation.spec.ts b/desktop/packages/mullvad-vpn/test/unit/notification-evaluation.spec.ts index 50acda1393..2a1924e52d 100644 --- a/desktop/packages/mullvad-vpn/test/unit/notification-evaluation.spec.ts +++ b/desktop/packages/mullvad-vpn/test/unit/notification-evaluation.spec.ts @@ -118,12 +118,12 @@ describe('System notifications', () => { it('Tunnel state notifications should respect notification setting', () => { const controller = createController(); - const disconnectedState: TunnelState = { state: 'disconnected' }; + const disconnectedState: TunnelState = { state: 'disconnected', lockedDown: false }; const connectingState: TunnelState = { state: 'connecting', featureIndicators: undefined }; - const result1 = controller.notifyTunnelState(disconnectedState, false, false, false, true); - const result2 = controller.notifyTunnelState(disconnectedState, false, false, false, false); - const result3 = controller.notifyTunnelState(connectingState, false, false, false, true); - const result4 = controller.notifyTunnelState(connectingState, false, false, false, false); + const result1 = controller.notifyTunnelState(disconnectedState, false, false, true); + const result2 = controller.notifyTunnelState(disconnectedState, false, false, false); + const result3 = controller.notifyTunnelState(connectingState, false, false, true); + const result4 = controller.notifyTunnelState(connectingState, false, false, false); expect(result1).to.be.true; expect(result2).to.be.false; @@ -136,7 +136,7 @@ describe('System notifications', () => { cause: ErrorStateCause.isOffline, }, }; - const result5 = controller.notifyTunnelState(blockingErrorState, false, false, false, false); + const result5 = controller.notifyTunnelState(blockingErrorState, false, false, false); expect(result5).to.be.false; const nonBlockingErrorState: TunnelState = { @@ -148,7 +148,7 @@ describe('System notifications', () => { }, }, }; - const result6 = controller.notifyTunnelState(nonBlockingErrorState, false, false, false, false); + const result6 = controller.notifyTunnelState(nonBlockingErrorState, false, false, false); expect(result6).to.be.true; }); }); |
