Skip to content

Commit

Permalink
Merge branch 'add-macos-split-tunneling-gui-des-786'
Browse files Browse the repository at this point in the history
  • Loading branch information
raksooo committed May 28, 2024
2 parents b6db0f3 + 58556c0 commit 2b04fed
Show file tree
Hide file tree
Showing 23 changed files with 1,298 additions and 595 deletions.
4 changes: 4 additions & 0 deletions gui/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ const namingConvention = [
{
selector: 'typeProperty',
format: ['camelCase'],
filter: {
regex: "^(data-testid|aria-labelledby|aria-describedby)$",
match: false,
},
},
{
selector: 'typeLike',
Expand Down
92 changes: 84 additions & 8 deletions gui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions gui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"react-redux": "^7.2.9",
"react-router": "^5.3.4",
"redux": "^4.2.0",
"simple-plist": "^1.3.1",
"sprintf-js": "^1.1.2",
"styled-components": "^6.1.0"
},
Expand Down
74 changes: 45 additions & 29 deletions gui/src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import util from 'util';

import config from '../config.json';
import { hasExpired } from '../shared/account-expiry';
import { IWindowsApplication } from '../shared/application-types';
import {
ISplitTunnelingApplication,
ISplitTunnelingAppListRetriever,
} from '../shared/application-types';
import {
AccessMethodSetting,
DaemonEvent,
Expand Down Expand Up @@ -52,6 +55,7 @@ import NotificationController, {
NotificationControllerDelegate,
NotificationSender,
} from './notification-controller';
import { isMacOs13OrNewer } from './platform-version';
import * as problemReport from './problem-report';
import { resolveBin } from './proc';
import ReconnectionBackoff from './reconnection-backoff';
Expand All @@ -67,7 +71,8 @@ const execAsync = util.promisify(exec);

// Only import split tunneling library on correct OS.
const linuxSplitTunneling = process.platform === 'linux' && require('./linux-split-tunneling');
const windowsSplitTunneling = process.platform === 'win32' && require('./windows-split-tunneling');
// This is used on Windows and macOS and will be undefined on Linux.
const splitTunneling: ISplitTunnelingAppListRetriever | undefined = importSplitTunneling();

const ALLOWED_PERMISSIONS = ['clipboard-sanitized-write'];

Expand Down Expand Up @@ -110,7 +115,7 @@ class ApplicationMain
private rendererLog?: Logger;
private translations: ITranslations = { locale: this.locale };

private windowsSplitTunnelingApplications?: IWindowsApplication[];
private splitTunnelingApplications?: ISplitTunnelingApplication[];

private macOsScrollbarVisibility?: MacOsScrollbarVisibility;

Expand Down Expand Up @@ -723,9 +728,7 @@ class ApplicationMain

IpcMainEventChannel.settings.notify?.(newSettings);

if (windowsSplitTunneling) {
void this.updateSplitTunnelingApplications(newSettings.splitTunnel.appsList);
}
void this.updateSplitTunnelingApplications(newSettings.splitTunnel.appsList);
}

private setRelayList(relayList: IRelayListWithEndpointData) {
Expand All @@ -734,12 +737,12 @@ class ApplicationMain
}

private async updateSplitTunnelingApplications(appList: string[]): Promise<void> {
const { applications } = await windowsSplitTunneling.getApplications({
applicationPaths: appList,
});
this.windowsSplitTunnelingApplications = applications;
if (splitTunneling) {
const { applications } = await splitTunneling.getMetadataForApplications(appList);
this.splitTunnelingApplications = applications;

IpcMainEventChannel.windowsSplitTunneling.notify?.(applications);
IpcMainEventChannel.splitTunneling.notify?.(applications);
}
}

private registerIpcListeners() {
Expand All @@ -758,12 +761,13 @@ class ApplicationMain
upgradeVersion: this.version.upgradeVersion,
guiSettings: this.settings.gui.state,
translations: this.translations,
windowsSplitTunnelingApplications: this.windowsSplitTunnelingApplications,
splitTunnelingApplications: this.splitTunnelingApplications,
macOsScrollbarVisibility: this.macOsScrollbarVisibility,
changelog: this.changelog ?? [],
forceShowChanges: CommandLineOptions.showChanges.match,
navigationHistory: this.navigationHistory,
currentApiAccessMethod: this.currentApiAccessMethod,
isMacOs13OrNewer: isMacOs13OrNewer(),
}));

IpcMainEventChannel.map.handleGetData(async () => ({
Expand All @@ -789,38 +793,38 @@ class ApplicationMain
IpcMainEventChannel.linuxSplitTunneling.handleGetApplications(() => {
return linuxSplitTunneling.getApplications(this.locale);
});
IpcMainEventChannel.windowsSplitTunneling.handleGetApplications((updateCaches: boolean) => {
return windowsSplitTunneling.getApplications({ updateCaches });
IpcMainEventChannel.splitTunneling.handleGetApplications((updateCaches: boolean) => {
return splitTunneling!.getApplications(updateCaches);
});
IpcMainEventChannel.linuxSplitTunneling.handleLaunchApplication((application) => {
return linuxSplitTunneling.launchApplication(application);
});

IpcMainEventChannel.windowsSplitTunneling.handleSetState((enabled) => {
IpcMainEventChannel.splitTunneling.handleSetState((enabled) => {
return this.daemonRpc.setSplitTunnelingState(enabled);
});
IpcMainEventChannel.windowsSplitTunneling.handleAddApplication(async (application) => {
IpcMainEventChannel.splitTunneling.handleAddApplication(async (application) => {
// If the applications is a string (path) it's an application picked with the file picker
// that we want to add to the list of additional applications.
if (typeof application === 'string') {
this.settings.gui.addBrowsedForSplitTunnelingApplications(application);
const applicationPath = await windowsSplitTunneling.addApplicationPathToCache(application);
await this.daemonRpc.addSplitTunnelingApplication(applicationPath);
const executablePath = await splitTunneling!.resolveExecutablePath(application);
await splitTunneling!.addApplicationPathToCache(application);
await this.daemonRpc.addSplitTunnelingApplication(executablePath);
} else {
await this.daemonRpc.addSplitTunnelingApplication(application.absolutepath);
}
});
IpcMainEventChannel.windowsSplitTunneling.handleRemoveApplication((application) => {
IpcMainEventChannel.splitTunneling.handleRemoveApplication((application) => {
return this.daemonRpc.removeSplitTunnelingApplication(
typeof application === 'string' ? application : application.absolutepath,
);
});
IpcMainEventChannel.windowsSplitTunneling.handleForgetManuallyAddedApplication(
(application) => {
this.settings.gui.deleteBrowsedForSplitTunnelingApplications(application.absolutepath);
return windowsSplitTunneling.removeApplicationFromCache(application);
},
);
IpcMainEventChannel.splitTunneling.handleForgetManuallyAddedApplication((application) => {
this.settings.gui.deleteBrowsedForSplitTunnelingApplications(application.absolutepath);
splitTunneling!.removeApplicationFromCache(application);
return Promise.resolve();
});

IpcMainEventChannel.app.handleQuit(() => this.disconnectAndQuit());
IpcMainEventChannel.app.handleOpenUrl(async (url) => {
Expand Down Expand Up @@ -851,10 +855,10 @@ class ApplicationMain
this.settings.registerIpcListeners();
this.account.registerIpcListeners();

if (windowsSplitTunneling) {
this.settings.gui.browsedForSplitTunnelingApplications.forEach(
windowsSplitTunneling.addApplicationPathToCache,
);
if (splitTunneling) {
this.settings.gui.browsedForSplitTunnelingApplications.forEach((application) => {
void splitTunneling.addApplicationPathToCache(application);
});
}
}

Expand Down Expand Up @@ -1104,6 +1108,18 @@ class ApplicationMain
/* eslint-enable @typescript-eslint/member-ordering */
}

function importSplitTunneling() {
if (process.platform === 'win32') {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { WindowsSplitTunnelingAppListRetriever } = require('./windows-split-tunneling');
return new WindowsSplitTunnelingAppListRetriever();
} else if (process.platform === 'darwin') {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { MacOsSplitTunnelingAppListRetriever } = require('./macos-split-tunneling');
return new MacOsSplitTunnelingAppListRetriever();
}
}

if (CommandLineOptions.help.match) {
console.log('Mullvad VPN');
console.log('Graphical interface for managing the Mullvad VPN daemon');
Expand Down
1 change: 0 additions & 1 deletion gui/src/main/linux-split-tunneling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ export async function getApplications(locale: string): Promise<ILinuxSplitTunnel
const applications = desktopEntries
.filter(shouldShowApplication)
.map(addApplicationWarnings)
.sort((a, b) => a.name.localeCompare(b.name))
.map(replaceIconNameWithDataUrl);

return Promise.all(applications);
Expand Down
Loading

0 comments on commit 2b04fed

Please sign in to comment.