summaryrefslogtreecommitdiffhomepage
path: root/gui/src/main
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2022-03-30 09:23:28 +0200
committerOskar Nyberg <oskar@mullvad.net>2022-03-31 15:59:47 +0200
commita7d0e178604e740c695003ab2c99ef0216a516d2 (patch)
tree48ad63e293336314bc7777e1ad15c7ad52592079 /gui/src/main
parent296277eb75a58eff48addf31a7e8f4cf4d7ab4fd (diff)
downloadmullvadvpn-a7d0e178604e740c695003ab2c99ef0216a516d2.tar.xz
mullvadvpn-a7d0e178604e740c695003ab2c99ef0216a516d2.zip
Add button to delete browsed for split tunneling apps
Diffstat (limited to 'gui/src/main')
-rw-r--r--gui/src/main/gui-settings.ts9
-rw-r--r--gui/src/main/index.ts70
-rw-r--r--gui/src/main/windows-split-tunneling.ts26
3 files changed, 51 insertions, 54 deletions
diff --git a/gui/src/main/gui-settings.ts b/gui/src/main/gui-settings.ts
index 73c546a24b..a4e7a31d22 100644
--- a/gui/src/main/gui-settings.ts
+++ b/gui/src/main/gui-settings.ts
@@ -90,6 +90,15 @@ export default class GuiSettings {
});
}
+ public deleteBrowsedForSplitTunnelingApplications(path: string) {
+ this.changeStateAndNotify({
+ ...this.stateValue,
+ browsedForSplitTunnelingApplications: this.browsedForSplitTunnelingApplications.filter(
+ (application) => application !== path,
+ ),
+ });
+ }
+
get browsedForSplitTunnelingApplications(): Array<string> {
return this.stateValue.browsedForSplitTunnelingApplications;
}
diff --git a/gui/src/main/index.ts b/gui/src/main/index.ts
index a6fcfa7be7..4ab0cbdd93 100644
--- a/gui/src/main/index.ts
+++ b/gui/src/main/index.ts
@@ -18,7 +18,7 @@ import * as path from 'path';
import util from 'util';
import config from '../config.json';
import { closeToExpiry, hasExpired } from '../shared/account-expiry';
-import { IApplication } from '../shared/application-types';
+import { IWindowsApplication } from '../shared/application-types';
import BridgeSettingsBuilder from '../shared/bridge-settings-builder';
import {
AccountToken,
@@ -241,7 +241,7 @@ class ApplicationMain {
private rendererLog?: Logger;
private translations: ITranslations = { locale: this.locale };
- private windowsSplitTunnelingApplications?: IApplication[];
+ private windowsSplitTunnelingApplications?: IWindowsApplication[];
private macOsScrollbarVisibility?: MacOsScrollbarVisibility;
@@ -1331,66 +1331,40 @@ class ApplicationMain {
});
IpcMainEventChannel.linuxSplitTunneling.handleGetApplications(() => {
- if (linuxSplitTunneling) {
- return linuxSplitTunneling.getApplications(this.locale);
- } else {
- throw Error('linuxSplitTunneling.getApplications function called without being imported');
- }
+ return linuxSplitTunneling.getApplications(this.locale);
});
IpcMainEventChannel.windowsSplitTunneling.handleGetApplications((updateCaches: boolean) => {
- if (windowsSplitTunneling) {
- return windowsSplitTunneling.getApplications({
- updateCaches,
- });
- } else {
- throw Error('windowsSplitTunneling.getApplications function called without being imported');
- }
+ return windowsSplitTunneling.getApplications({ updateCaches });
});
IpcMainEventChannel.linuxSplitTunneling.handleLaunchApplication((application) => {
- if (linuxSplitTunneling) {
- return linuxSplitTunneling.launchApplication(application);
- } else {
- throw Error('linuxSplitTunneling.launchApplication function called without being imported');
- }
+ return linuxSplitTunneling.launchApplication(application);
});
IpcMainEventChannel.windowsSplitTunneling.handleSetState((enabled) => {
- if (windowsSplitTunneling) {
- return this.daemonRpc.setSplitTunnelingState(enabled);
- } else {
- throw Error('windowsSplitTunneling.setState function called without being imported');
- }
+ return this.daemonRpc.setSplitTunnelingState(enabled);
});
IpcMainEventChannel.windowsSplitTunneling.handleAddApplication(async (application) => {
- if (windowsSplitTunneling) {
- // 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.guiSettings.addBrowsedForSplitTunnelingApplications(application);
- const applicationPath = await windowsSplitTunneling.addApplicationPathToCache(
- application,
- );
- await this.daemonRpc.addSplitTunnelingApplication(applicationPath);
- } else {
- await this.daemonRpc.addSplitTunnelingApplication(application.absolutepath);
- }
+ // 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.guiSettings.addBrowsedForSplitTunnelingApplications(application);
+ const applicationPath = await windowsSplitTunneling.addApplicationPathToCache(application);
+ await this.daemonRpc.addSplitTunnelingApplication(applicationPath);
} else {
- throw Error(
- 'windowsSplitTunneling.handleAddApplication function called without being imported',
- );
+ await this.daemonRpc.addSplitTunnelingApplication(application.absolutepath);
}
});
IpcMainEventChannel.windowsSplitTunneling.handleRemoveApplication((application) => {
- if (windowsSplitTunneling) {
- return this.daemonRpc.removeSplitTunnelingApplication(
- typeof application === 'string' ? application : application.absolutepath,
- );
- } else {
- throw Error(
- 'windowsSplitTunneling.handleRemoveApplication function called without being imported',
- );
- }
+ return this.daemonRpc.removeSplitTunnelingApplication(
+ typeof application === 'string' ? application : application.absolutepath,
+ );
});
+ IpcMainEventChannel.windowsSplitTunneling.handleForgetManuallyAddedApplication(
+ (application) => {
+ this.guiSettings.deleteBrowsedForSplitTunnelingApplications(application.absolutepath);
+ return windowsSplitTunneling.removeApplicationFromCache(application);
+ },
+ );
IpcMainEventChannel.problemReport.handleCollectLogs((toRedact) => {
const id = randomUUID();
diff --git a/gui/src/main/windows-split-tunneling.ts b/gui/src/main/windows-split-tunneling.ts
index a8915595e5..2ae118db4a 100644
--- a/gui/src/main/windows-split-tunneling.ts
+++ b/gui/src/main/windows-split-tunneling.ts
@@ -1,7 +1,7 @@
import { app, shell } from 'electron';
import fs from 'fs';
import path from 'path';
-import { IApplication } from '../shared/application-types';
+import { IWindowsApplication } from '../shared/application-types';
import log from '../shared/logging';
import {
ArrayValue,
@@ -35,6 +35,7 @@ interface ShortcutDetails {
target: string;
name: string;
args?: string;
+ deletable: boolean;
}
type RvaToOffset = (rva: number) => Promise<number>;
@@ -58,9 +59,9 @@ const APPLICATION_ALLOW_LIST = [
// Cache of all previously scanned shortcuts.
const shortcutCache: Record<string, ShortcutDetails> = {};
// Cache of all previously scanned applications.
-const applicationCache: Record<string, IApplication> = {};
+const applicationCache: Record<string, IWindowsApplication> = {};
// List of shortcuts that have been added manually by the user.
-const additionalShortcuts: ShortcutDetails[] = [];
+let additionalShortcuts: ShortcutDetails[] = [];
// Finds applications by searching through the startmenu for shortcuts with and exe-file as target.
// If applicationPaths has a value, the returned applications are only the ones corresponding to
@@ -68,7 +69,7 @@ const additionalShortcuts: ShortcutDetails[] = [];
export async function getApplications(options: {
applicationPaths?: string[];
updateCaches?: boolean;
-}): Promise<{ fromCache: boolean; applications: IApplication[] }> {
+}): Promise<{ fromCache: boolean; applications: IWindowsApplication[] }> {
const cacheIsEmpty = Object.keys(shortcutCache).length === 0;
if (options.updateCaches || cacheIsEmpty) {
@@ -105,7 +106,11 @@ export async function addApplicationPathToCache(applicationPath: string): Promis
const parsedPath = path.parse(applicationPath);
if (parsedPath.ext === '.lnk') {
const shortcutDetiails = shell.readShortcutLink(path.resolve(applicationPath));
- additionalShortcuts.push({ ...shortcutDetiails, name: path.parse(applicationPath).name });
+ additionalShortcuts.push({
+ ...shortcutDetiails,
+ name: path.parse(applicationPath).name,
+ deletable: true,
+ });
return shortcutDetiails.target;
} else {
await addApplicationToAdditionalShortcuts(applicationPath);
@@ -113,6 +118,13 @@ export async function addApplicationPathToCache(applicationPath: string): Promis
}
}
+export function removeApplicationFromCache(application: IWindowsApplication): void {
+ additionalShortcuts = additionalShortcuts.filter(
+ (shortcut) => shortcut.target !== application.absolutepath,
+ );
+ delete applicationCache[application.absolutepath.toLowerCase()];
+}
+
// Reads the start-menu directories and adds all shortcuts, targeting applications using networking,
// to the shortcuts cache. Wheter or not an application use networking is determined by checking for
// "WS2_32.dll" in it's imports.
@@ -158,6 +170,7 @@ async function addApplicationToAdditionalShortcuts(applicationPath: string): Pro
additionalShortcuts.push({
target: applicationPath,
name: (await getProgramName(applicationPath)) ?? path.parse(applicationPath).name,
+ deletable: true,
});
}
}
@@ -231,11 +244,12 @@ function removeDuplicates(shortcuts: ShortcutDetails[]): ShortcutDetails[] {
async function convertToSplitTunnelingApplication(
shortcut: ShortcutDetails,
-): Promise<IApplication> {
+): Promise<IWindowsApplication> {
return {
absolutepath: shortcut.target,
name: shortcut.name,
icon: await retrieveIcon(shortcut.target),
+ deletable: shortcut.deletable,
};
}