Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Auto connect on insecure wifi #101

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/ProtonVPN.App/App.config
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,12 @@
<setting name="ConnectOnAppStart" serializeAs="String">
<value>True</value>
</setting>
<setting name="ConnectOnInsecureWifi" serializeAs="String">
<value>True</value>
</setting>
<setting name="SecureDisconnect" serializeAs="String">
<value>True</value>
</setting>
<setting name="StartOnBoot" serializeAs="String">
<value>True</value>
</setting>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ private IEnumerable<KeyValuePair<string, dynamic>> GetProperties()
yield return new(nameof(IAppSettings.AppFirstRun), _appSettings.AppFirstRun);
yield return new(nameof(IAppSettings.ShowNotifications), _appSettings.ShowNotifications);
yield return new(nameof(IAppSettings.ConnectOnAppStart), _appSettings.ConnectOnAppStart);
yield return new(nameof(IAppSettings.ConnectOnInsecureWifi), _appSettings.ConnectOnInsecureWifi);
yield return new(nameof(IAppSettings.QuickConnect), _appSettings.QuickConnect);
yield return new(nameof(IAppSettings.StartOnBoot), _appSettings.StartOnBoot);
yield return new(nameof(IAppSettings.StartMinimized), _appSettings.StartMinimized);
Expand Down
12 changes: 12 additions & 0 deletions src/ProtonVPN.App/Core/AppSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,18 @@ public bool ConnectOnAppStart
set => Set(value);
}

public bool ConnectOnInsecureWifi
{
get => Get<bool>();
set => Set(value);
}

public bool SecureDisconnect
{
get => Get<bool>();
set => Set(value);
}

[Obsolete(
"Use this only for checking if the user enabled/disabled the feature." +
"Use IsSmartReconnectEnabled() for checking if Smart Reconnect is/should be enabled.")]
Expand Down
55 changes: 55 additions & 0 deletions src/ProtonVPN.App/Core/AutoConnect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,31 @@
using ProtonVPN.Core.Service.Vpn;
using ProtonVPN.Core.Settings;
using ProtonVPN.Core.Vpn;
using ProtonVPN.Core.Network;

namespace ProtonVPN.Core
{
internal class AutoConnect : IVpnStateAware
{
private readonly IAppSettings _appSettings;
private readonly INetworkClient _networkClient;
private readonly IVpnManager _vpnManager;
private readonly ILogger _logger;
private VpnStatus _vpnStatus;
private bool _connectedToInsecureWifi;

public AutoConnect(
IAppSettings appSettings,
INetworkClient networkClient,
IVpnManager vpnManager,
ILogger logger)
{
_appSettings = appSettings;
_networkClient = networkClient;
_vpnManager = vpnManager;
_logger = logger;

_networkClient.WifiChangeDetected += OnWifiChangeDetected;
}

public async Task LoadAsync(bool autoLogin)
Expand Down Expand Up @@ -75,5 +82,53 @@ public Task OnVpnStateChanged(VpnStateChangedEventArgs e)

return Task.CompletedTask;
}

private bool InsecureWifiAutoConnectionRequired(bool isSecure)
{
return !isSecure && _vpnStatus.Equals(VpnStatus.Disconnected) && _appSettings.ConnectOnInsecureWifi;
}
private bool InsecureWifiSecureDisconnectRequired(bool isSecure)
{
return isSecure && _vpnStatus.Equals(VpnStatus.Connected) && _connectedToInsecureWifi && _appSettings.SecureDisconnect;
}

private void OnWifiChangeDetected(object sender, WifiChangeEventArgs e)
{
if (_appSettings.ConnectOnInsecureWifi)
{
if (InsecureWifiSecureDisconnectRequired(e.Secure))
{
Task.Factory.StartNew(async () =>
{
try
{
_logger.Info<ConnectTriggerLog>("Automatically disconnecting on secure wifi");
await _vpnManager.DisconnectAsync();
}
catch (OperationCanceledException ex)
{
_logger.Error<AppLog>("An error occurred when disconnecting automatically on secure wifi.", ex);
}
});
}
else if (InsecureWifiAutoConnectionRequired(e.Secure))
{
Task.Factory.StartNew(async () =>
{
try
{
_logger.Info<ConnectTriggerLog>("Automatically connecting on insecure wifi");
await _vpnManager.QuickConnectAsync();
}
catch (OperationCanceledException ex)
{
_logger.Error<AppLog>("An error occurred when connecting automatically on insecure wifi.", ex);
}
});
}
}

_connectedToInsecureWifi = !e.Secure;
}
}
}
24 changes: 24 additions & 0 deletions src/ProtonVPN.App/Properties/Settings.Designer.cs

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

6 changes: 6 additions & 0 deletions src/ProtonVPN.App/Properties/Settings.settings
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,12 @@
<Setting Name="ConnectOnAppStart" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="ConnectOnInsecureWifi" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="SecureDisconnect" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="StartOnBoot" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ namespace ProtonVPN.Settings.Migrations.v1_27_1
internal class AppSettingsMigration : BaseAppSettingsMigration
{
private const string UserAutoConnectKey = "UserAutoConnect";
private const string UserAutoConnectOnInsecureWifiKey = "ConnectOnInsecureWifi";
private const string UserSecureDisconnectKey = "SecureDisconnect";
private const string StartOnStartupKey = "StartOnStartup";

private readonly InitialAppSettingsMigration _initialAppSettingsMigration;
Expand All @@ -53,6 +55,18 @@ private void MigrateAutoConnect()
bool autoConnect = autoConnectSettings.Any(setting => !setting.Value.IsNullOrEmpty());
Settings.Set(nameof(IAppSettings.ConnectOnAppStart), _initialAppSettingsMigration.IsCleanInstall || autoConnect);
}
PerUser<string>[] autoConnectOnInsecureSettings = Settings.Get<PerUser<string>[]>(UserAutoConnectOnInsecureWifiKey);
if (autoConnectOnInsecureSettings != null)
{
bool autoConnect = autoConnectOnInsecureSettings.Any(setting => !setting.Value.IsNullOrEmpty());
Settings.Set(nameof(IAppSettings.ConnectOnInsecureWifi), _initialAppSettingsMigration.IsCleanInstall || autoConnect);
}
PerUser<string>[] secureDisconnectSettings = Settings.Get<PerUser<string>[]>(UserSecureDisconnectKey);
if (secureDisconnectSettings != null)
{
bool secureDisconnect = secureDisconnectSettings.Any(setting => !setting.Value.IsNullOrEmpty());
Settings.Set(nameof(IAppSettings.SecureDisconnect), _initialAppSettingsMigration.IsCleanInstall || secureDisconnect);
}
}

private void MigrateStartOnStartup()
Expand Down
34 changes: 34 additions & 0 deletions src/ProtonVPN.App/Settings/SettingsModalView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,40 @@ along with ProtonVPN. If not, see <https://www.gnu.org/licenses/>.
</DockPanel>
</Border>

<Border Style="{StaticResource BorderlessSettingContainer}">
<DockPanel>
<StackPanel Orientation="Horizontal">
<Label Style="{StaticResource SettingName}"
Content="{translations:Loc Settings_General_lbl_ConnectOnInsecureWifi}" />
<icons:InfoCircleFilled Style="{StaticResource InfoCircle}"
ToolTip="{translations:Loc Settings_General_lbl_ConnectOnInsecureWifi_Info}"/>
</StackPanel>
<CheckBox Margin="0,0,14,0"
HorizontalAlignment="Right"
Style="{StaticResource ToggleSwitch}"
IsChecked="{Binding ConnectOnInsecureWifi}"
AutomationProperties.AutomationId="{StaticResource ConnectOnInsecureWifiCheckbox}" />
</DockPanel>
</Border>

<Border Style="{StaticResource BorderSettingContainer}">
<DockPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Style="{StaticResource SubSettingIcon}" />
<Label Style="{StaticResource SettingName}" Margin="5,0,0,0"
Content="{translations:Loc Settings_General_lbl_SecureDisconnect}"/>
<icons:InfoCircleFilled Style="{StaticResource InfoCircle}"
ToolTip="{translations:Loc Settings_General_lbl_SecureDisconnect_Info}"/>
</StackPanel>

<CheckBox Style="{StaticResource ToggleSwitch}"
Margin="0,0,14,0"
HorizontalAlignment="Right"
IsChecked="{Binding SecureDisconnect}"
AutomationProperties.AutomationId="{StaticResource SecureDisconnectCheckbox}"/>
</DockPanel>
</Border>

<Border Style="{StaticResource BorderSettingContainer}">
<DockPanel>
<Label Style="{StaticResource SettingName}" Content="{translations:Loc Settings_General_lbl_ShowNotifications}"/>
Expand Down
12 changes: 12 additions & 0 deletions src/ProtonVPN.App/Settings/SettingsModalViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,18 @@ public bool ConnectOnAppStart
set => _appSettings.ConnectOnAppStart = value;
}

public bool ConnectOnInsecureWifi
{
get => _appSettings.ConnectOnInsecureWifi;
set => _appSettings.ConnectOnInsecureWifi = value;
}

public bool SecureDisconnect
{
get => _appSettings.SecureDisconnect;
set => _appSettings.SecureDisconnect = value;
}

public bool ShowNotifications
{
get => _appSettings.ShowNotifications;
Expand Down
1 change: 1 addition & 0 deletions src/ProtonVPN.Core/ProtonVPN.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<PackageReference Include="Newtonsoft.Json">
<Version>13.0.3</Version>
</PackageReference>
<PackageReference Include="Srp.ProtonMail" Version="0.1.0" />
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="Caliburn.Micro.Core" Version="4.0.212" />
Expand Down
2 changes: 2 additions & 0 deletions src/ProtonVPN.Core/Settings/IAppSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ public interface IAppSettings
bool FeaturePromoCodeEnabled { get; set; }
bool FeatureFreeRescopeEnabled { get; set; }
bool ConnectOnAppStart { get; set; }
bool ConnectOnInsecureWifi { get; set; }
bool SecureDisconnect { get; set; }
bool FeatureSmartReconnectEnabled { get; set; }
bool ShowNonStandardPortsToFreeUsers { get; set; }
bool SmartReconnectEnabled { get; set; }
Expand Down
2 changes: 2 additions & 0 deletions src/ProtonVPN.Resources/Automation/Config.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ along with ProtonVPN. If not, see <https://www.gnu.org/licenses/>.
<system:String x:Key="PortForwardingOnButton">PortForwardingOnButton</system:String>
<system:String x:Key="PortForwardingOffButton">PortForwardingOffButton</system:String>
<system:String x:Key="ConnectOnBootCheckbox">ConnectOnBootCheckbox</system:String>
<system:String x:Key="ConnectOnInsecureWifiCheckbox">ConnectOnInsecureWifi</system:String>
<system:String x:Key="SecureDisconnectCheckbox">SecureDisconnect</system:String>
<system:String x:Key="CancelActionButton">CancelActionButton</system:String>
<system:String x:Key="QuickLaunchFlag">QuickLaunchFlag</system:String>
<system:String x:Key="UpsellModalTitle">UpsellModalTitle</system:String>
Expand Down
38 changes: 37 additions & 1 deletion src/ProtonVPN.Translations/Properties/Resources.Designer.cs

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

16 changes: 16 additions & 0 deletions src/ProtonVPN.Translations/Properties/Resources.en-US.resx
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,14 @@
<value>Automatically connect to the Quick Connect profile when Proton VPN starts.</value>
<comment>The description of Connect on boot setting displayed in the tooltip of ( i ) image next to the label for Connect on boot combo box in General tab of Settings window</comment>
</data>
<data name="Settings_General_lbl_ConnectOnInsecureWifi_Info" xml:space="preserve">
<value>Automatically connect to the Quick Connect profile when connecting to an insecure wifi.</value>
<comment>The description of Connect on insecure wifi setting displayed in the tooltip of ( i ) image next to the label for Connect on insecure wifi combo box in General tab of Settings window</comment>
</data>
<data name="Settings_General_lbl_SecureDisconnect_Info" xml:space="preserve">
<value>Automatically disconnect once connected to a secure wifi.</value>
<comment>The description of Connect on insecure wifi setting displayed in the tooltip of ( i ) image next to the label for Disconnect on secure wifi combo box in General tab of Settings window</comment>
</data>
<data name="StartMinimizedMode_val_Disabled" xml:space="preserve">
<value>Disabled</value>
<comment>The name of start minimized mode displayed in Start Minimized combo box in General tab of Settings window</comment>
Expand Down Expand Up @@ -709,6 +717,14 @@ This setting instructs the Proton VPN to start automatically when the user logs
<value>Connect on app start</value>
<comment>The label for Connect on boot combo box in General tab of Settings window</comment>
</data>
<data name="Settings_General_lbl_ConnectOnInsecureWifi" xml:space="preserve">
<value>Connect when connected to an insecure wifi</value>
<comment>The label for Connect on insecure wifi combo box in General tab of Settings window</comment>
</data>
<data name="Settings_General_lbl_SecureDisconnect" xml:space="preserve">
<value>Disconnect on secured wifi</value>
<comment>The label for Disconnecting when connected to a secured wifi combo box in General tab of Settings window</comment>
</data>
<data name="About_lbl_ChangelogVersion" xml:space="preserve">
<value>Changelog of v.{0}</value>
<comment>The title of app version in change log in About window. The {0} is a placeholder for app version number.</comment>
Expand Down
14 changes: 14 additions & 0 deletions src/Tests/ProtonVPN.UI.Tests/Windows/SettingsWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public class SettingsWindow : UIActions
private ListBoxItem OptionDisabled => StartMinimizedComboBox.FindFirstChild().AsListBoxItem();
private Button SettingsCloseButton => ElementByAutomationId("ModalCloseButton").AsButton();
private CheckBox ConnectOnBootCheckBox => ElementByAutomationId("ConnectOnBootCheckbox").AsCheckBox();
private CheckBox ConnectOnInsecureWifiCheckBox => ElementByAutomationId("ConnectOnInsecureWifiCheckbox").AsCheckBox();
private CheckBox SecureDisconnectCheckBox => ElementByAutomationId("SecureDisconnectCheckbox").AsCheckBox();
private AutomationElement ConnectionTab => ElementByName("Connection").FindFirstChild();
private AutomationElement AdvancedTab => ElementByName("Advanced").FindFirstChild();
private CheckBox CustomDnsCheckBox => ElementByAutomationId("CheckBoxCustomDnsServers").AsCheckBox();
Expand All @@ -55,6 +57,18 @@ public SettingsWindow ClickOnConnectOnBoot()
return this;
}

public SettingsWindow ClickOnConnectOnInsecureWifi()
{
ConnectOnInsecureWifiCheckBox.Click();
return this;
}

public SettingsWindow ClickOnSecureDisconnect()
{
SecureDisconnectCheckBox.Click();
return this;
}

public HomeWindow CloseSettings()
{
SettingsCloseButton.Invoke();
Expand Down