Skip to content

Commit

Permalink
Merge branch 'release/3.2.10'
Browse files Browse the repository at this point in the history
  • Loading branch information
Mindaugas Veblauskas committed Feb 22, 2024
2 parents a8792d8 + e1f4018 commit 9ef8b62
Show file tree
Hide file tree
Showing 38 changed files with 450 additions and 368 deletions.
4 changes: 2 additions & 2 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ prepare-internal-beta-release:
mirror:
stage: mirror
tags:
- windows
- windows-dot-net
only:
refs:
- tags
Expand Down Expand Up @@ -248,7 +248,7 @@ create-release:

send-slack-notification:
tags:
- windows
- windows-dot-net
only:
refs:
- develop
Expand Down
2 changes: 1 addition & 1 deletion Setup/CodeDependencies.iss
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type
var
Dependency_Memo: String;
Dependency_List: array of TDependency_Entry;
Dependency_NeedRestart, Dependency_ForceX86: Boolean;
Dependency_NeedRestart: Boolean;
Dependency_DownloadPage: TDownloadWizardPage;
procedure Dependency_Add(const Filename, Parameters, Title, URL, Checksum: String; const ForceSuccess, RestartAfter: Boolean);
Expand Down
70 changes: 26 additions & 44 deletions Setup/setup.iss
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define NetworkDriverFileName "Resources\ProtonVPN.CalloutDriver.sys"

#define ProtonDriveDownloaderName "ProtonDrive.Downloader.exe"
#define InstallLogPath "{app}\Install.log.txt"

#define Hash ""
#define VersionFolder "v" + MyAppVersion
Expand All @@ -33,9 +34,10 @@
[Setup]
AppName={#MyAppName}
AppVersion={#MyAppVersion}
DefaultDirName={pf}
DefaultDirName={autopf}\{#AppFolder}
DefaultGroupName=Proton
DisableDirPage=auto
DisableDirPage=yes
AlwaysShowDirOnReadyPage=yes
DisableProgramGroupPage=auto
AppPublisher={#MyPublisher}
UninstallDisplayIcon={app}\{#LauncherExeName}
Expand Down Expand Up @@ -159,13 +161,9 @@ Name: "uk_UA"; MessagesFile: "compiler:Languages\Ukrainian.isl,Strings\Ukrainian
Name: "tr_TR"; MessagesFile: "compiler:Languages\Turkish.isl,Strings\Turkish.isl"

[UninstallDelete]
Type: filesandordirs; Name: "{commonappdata}\ProtonVPN"
Type: filesandordirs; Name: "{localappdata}\ProtonVPN"
Type: filesandordirs; Name: "{app}\{#VersionFolder}\ServiceData"
Type: filesandordirs; Name: "{app}\{#VersionFolder}\Resources"

[Dirs]
Name: "{localappdata}\ProtonVPN\DiagnosticLogs"
Name: "{commonappdata}\ProtonVPN\Updates"; AfterInstall: SetFolderPermissions;
Type: files; Name: "{#InstallLogPath}"

[Code]
function InitLogger(logger: Longword): Integer;
Expand All @@ -183,9 +181,6 @@ external 'UninstallProduct@files:ProtonVPN.InstallActions.x86.dll cdecl delayloa
function IsProductInstalled(upgradeCode: String): Integer;
external 'IsProductInstalled@files:ProtonVPN.InstallActions.x86.dll cdecl delayload';
function SetUpdatesFolderPermission(updatesFolderPath: String): Integer;
external 'SetUpdatesFolderPermission@files:ProtonVPN.InstallActions.x86.dll cdecl delayload';
function UninstallTapAdapter(tapFilesPath: String): Integer;
external 'UninstallTapAdapter@ProtonVPN.InstallActions.x86.dll cdecl delayload uninstallonly';
Expand Down Expand Up @@ -226,7 +221,7 @@ type
TInt64Array = array of Int64;
var
IsToReboot, IsVerySilent, IsToDisableAutoUpdate, IsInstallPathModified: Boolean;
IsToReboot, IsVerySilent, IsToDisableAutoUpdate: Boolean;
function NeedRestart(): Boolean;
begin
Expand All @@ -248,11 +243,6 @@ begin
end;
end;
procedure SetFolderPermissions();
begin
SetUpdatesFolderPermission(ExpandConstant('{commonappdata}\ProtonVPN\Updates'));
end;
procedure DeleteNonRunningVersions(const Directory: string);
var
VersionFolder: TFindRec;
Expand Down Expand Up @@ -351,13 +341,22 @@ begin
if IsToDisableAutoUpdate = true then begin
Log('The app will be launched with auto updates disabled.');
end;
end;
// Returns 0 (zero) if versions are equal, -1 (negative one) if version1 is older and 1 (positive one) if version1 is more recent
function CompareVersions(version1, version2: String): Integer;
var
packVersion1, packVersion2: Int64;
begin
if not StrToVersion(version1, packVersion1) then packVersion1 := 0;
if not StrToVersion(version2, packVersion2) then packVersion2 := 0;
Result := ComparePackedVersion(packVersion1, packVersion2);
end;
function InitializeSetup(): Boolean;
var
Version: String;
ErrCode: Integer;
WindowsVersion: TWindowsVersion;
begin
SetIsVerySilent();
SetIsToDisableAutoUpdate();
Expand All @@ -371,7 +370,7 @@ begin
end;
if RegValueExists(HKEY_LOCAL_MACHINE,'Software\Microsoft\Windows\CurrentVersion\Uninstall\{#MyAppName}_is1', 'DisplayVersion') then begin
RegQueryStringValue(HKEY_LOCAL_MACHINE,'Software\Microsoft\Windows\CurrentVersion\Uninstall\{#MyAppName}_is1', 'DisplayVersion', Version);
if Version > '{#MyAppVersion}' then begin
if CompareVersions(Version, '{#MyAppVersion}') > 0 then begin
if WizardSilent() = false then begin
MsgBox(ExpandConstant('{#MyAppName} is already installed with the newer version ' + Version + '.'), mbInformation, MB_OK);
end;
Expand Down Expand Up @@ -414,24 +413,19 @@ begin
end;
function PrepareToInstall(var NeedsRestart: Boolean): String;
var
vpnFolderPath: String;
begin
vpnFolderPath := '{app}';
if IsUpgrade = False then
vpnFolderPath := vpnFolderPath + '\{#AppFolder}';
DeleteNonRunningVersions(ExpandConstant(vpnFolderPath));
DeleteNonRunningVersions(ExpandConstant('{app}'));
Log('Trying to save user settings for the old ProtonVPN app if it is installed');
SaveOldUserConfigFolder();
Log('Trying to update taskbar icon path if exists');
UpdateTaskbarIconTarget(ExpandConstant(vpnFolderPath + '\{#VersionFolder}\{#MyAppExeName}'));
UpdateTaskbarIconTarget(ExpandConstant('{app}\{#VersionFolder}\{#MyAppExeName}'));
Log('Trying to uninstall an old version of ProtonVPN app');
UninstallProduct('{2B10124D-2F81-4BB1-9165-4F9B1B1BA0F9}');
Log('Trying to uninstall an old version of ProtonVPN TUN adapter');
UninstallProduct('{FED0679F-A292-4507-AEF5-DD2BB8898A36}');
Log('Trying to uninstall an old version of ProtonVPN TAP adapter');
UninstallProduct('{E23B9F7F-AA0A-481A-8ECA-FA69794BF50A}');
Result := '';
end;
procedure CurStepChanged(CurStep: TSetupStep);
Expand All @@ -442,7 +436,7 @@ begin
if CurStep = ssDone then begin
logfilepathname := ExpandConstant('{log}');
logfilename := ExtractFileName(logfilepathname);
newfilepathname := ExpandConstant('{localappdata}') + '\ProtonVPN\DiagnosticLogs\ProtonVPN_install.log';
newfilepathname := ExpandConstant('{#InstallLogPath}');
FileCopy(logfilepathname, newfilepathname, false);
if IsProcessRunning('{#MyAppExeName}') then begin
exit;
Expand Down Expand Up @@ -485,24 +479,12 @@ begin
end;
end;
function ShouldDisplayProtonDriveCheckbox: Boolean;
begin
Result := IsProductInstalled('{F3B95BD2-1311-4B82-8B4A-B9EB7C0500ED}') = 0;
end;
function GetDriveInstallPath(value: String): String;
var
path: String;
begin
path := WizardForm.DirEdit.Text;
StringChangeEx(path, ExpandConstant('\{#AppFolder}'), '\Proton\Drive', True);
Result := '"' + path + '"';
Result := '"' + ExpandConstant('{autopf}\Proton\Drive') + '"';
end;
procedure CurPageChanged(CurPageID: Integer);
function ShouldDisplayProtonDriveCheckbox: Boolean;
begin
if (CurPageID = wpPreparing) and (IsInstallPathModified = False) and (IsUpgrade = False) then begin
IsInstallPathModified := true;
WizardForm.DirEdit.Text := WizardForm.DirEdit.Text + ExpandConstant('\{#AppFolder}');
end;
end;
Result := IsProductInstalled('{F3B95BD2-1311-4B82-8B4A-B9EB7C0500ED}') = 0;
end;
13 changes: 12 additions & 1 deletion ci/test-scripts/uninstall-app.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
$protonFolder = "C:\Program Files\Proton\VPN"
$regPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Proton VPN_is1"
$protonDataFolder = "C:\ProgramData\ProtonVPN"
$processes = Get-Process | Where-Object { $_.ProcessName -like "*ProtonVPN*" }
$userProfileFolder = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::UserProfile)
$protonLocalFolder = Join-Path -Path $userProfileFolder -ChildPath "AppData\Local\Proton\Proton VPN"

foreach ($process in $processes) {
Write-Host "Killing process $($process.ProcessName) (ID: $($process.Id))"
Expand All @@ -16,4 +19,12 @@ if (Test-Path -Path $protonFolder) {

if (Test-Path $regPath) {
Remove-Item -Path $regPath -Force
}
}

if (Test-Path -Path $protonLocalFolder) {
Remove-Item -Path $protonLocalFolder -Force -Recurse -ErrorAction Ignore
}

if (Test-Path -Path $protonDataFolder) {
Remove-Item -Path $protonDataFolder -Force -Recurse -ErrorAction Ignore
}
32 changes: 32 additions & 0 deletions src/Api/ProtonVPN.Api.Contracts/IVpnStatusNotifier.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2023 Proton AG
*
* This file is part of ProtonVPN.
*
* ProtonVPN is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonVPN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonVPN. If not, see <https://www.gnu.org/licenses/>.
*/


using System;
using ProtonVPN.Common.Vpn;

namespace ProtonVPN.Api.Contracts
{
public interface IVpnStatusNotifier
{
event EventHandler<VpnStatus> VpnStatusChanged;

void OnVpnStateChanged(VpnStatus status);
}
}
44 changes: 24 additions & 20 deletions src/Api/ProtonVPN.Api.Tests/ApiHostProviderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,13 @@
*/

using System;
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NSubstitute;
using ProtonVPN.Api.Contracts;
using ProtonVPN.Common.Configuration;
using ProtonVPN.Common.Vpn;
using ProtonVPN.Core.Settings;
using ProtonVPN.Core.Vpn;

namespace ProtonVPN.Api.Tests
{
Expand All @@ -37,77 +36,77 @@ public class ApiHostProviderTest
private const string PROXY_HOST = "alternative.api.url";
private IConfiguration _config;
private IAppSettings _appSettings;
private IVpnStatusNotifier _vpnStatusNotifier;

[TestInitialize]
public void Initialize()
{
_config = new Config() { Urls = { ApiUrl = API_URL } };
_config = new Config { Urls = { ApiUrl = API_URL } };
_appSettings = Substitute.For<IAppSettings>();
_vpnStatusNotifier = Substitute.For<IVpnStatusNotifier>();
}

[TestCleanup]
public void Cleanup()
{
_config = null;
_appSettings = null;
_vpnStatusNotifier = null;
}

[TestMethod]
public async Task ItShouldReturnAlternativeApiHostWhenProxyIsActivated()
public void ItShouldReturnAlternativeApiHostWhenProxyIsActivated()
{
// Arrange
_appSettings.DoHEnabled.Returns(true);
_appSettings.LastPrimaryApiFailDateUtc.Returns(DateTime.UtcNow.Subtract(TimeSpan.FromHours(2)));
_appSettings.ActiveAlternativeApiBaseUrl.Returns(PROXY_HOST);
ApiHostProvider sut = new(_appSettings, _config);
await sut.OnVpnStateChanged(new VpnStateChangedEventArgs(new VpnState(VpnStatus.Disconnected), VpnError.None,
false));

ApiHostProvider sut = new(_appSettings, _config, _vpnStatusNotifier);
RaiseVpnStatusEvent(VpnStatus.Disconnected);

// Assert
sut.IsProxyActive().Should().BeTrue();
}

[TestMethod]
public async Task ProxyShouldBeDisabledWhenConnectedToVpn()
public void ProxyShouldBeDisabledWhenConnectedToVpn()
{
// Arrange
_appSettings.DoHEnabled.Returns(true);
_appSettings.LastPrimaryApiFailDateUtc.Returns(DateTime.UtcNow.Subtract(TimeSpan.FromHours(2)));
_appSettings.ActiveAlternativeApiBaseUrl.Returns(PROXY_HOST);
ApiHostProvider sut = new(_appSettings, _config);
await sut.OnVpnStateChanged(new VpnStateChangedEventArgs(new VpnState(VpnStatus.Connected), VpnError.None,
false));
ApiHostProvider sut = new(_appSettings, _config, _vpnStatusNotifier);
RaiseVpnStatusEvent(VpnStatus.Connected);

// Assert
sut.IsProxyActive().Should().BeFalse();
}

[TestMethod]
public async Task ProxyShouldBeDisabledAfter24Hours()
public void ProxyShouldBeDisabledAfter24Hours()
{
// Arrange
_appSettings.DoHEnabled.Returns(true);
_appSettings.LastPrimaryApiFailDateUtc.Returns(DateTime.UtcNow.Subtract(TimeSpan.FromHours(25)));
_appSettings.ActiveAlternativeApiBaseUrl.Returns(PROXY_HOST);
ApiHostProvider sut = new(_appSettings, _config);
await sut.OnVpnStateChanged(new VpnStateChangedEventArgs(new VpnState(VpnStatus.Disconnected), VpnError.None,
false));
ApiHostProvider sut = new(_appSettings, _config, _vpnStatusNotifier);
RaiseVpnStatusEvent(VpnStatus.Disconnected);

// Assert
sut.IsProxyActive().Should().BeFalse();
}

[TestMethod]
public async Task ItShouldReturnAlternativeHostWhenProxyIsActive()
public void ItShouldReturnAlternativeHostWhenProxyIsActive()
{
// Arrange
_config.Urls.ApiUrl = API_URL;
_appSettings.ActiveAlternativeApiBaseUrl.Returns(PROXY_HOST);
_appSettings.DoHEnabled.Returns(true);
_appSettings.LastPrimaryApiFailDateUtc.Returns(DateTime.UtcNow.Subtract(TimeSpan.FromHours(2)));
ApiHostProvider sut = new(_appSettings, _config);
await sut.OnVpnStateChanged(new VpnStateChangedEventArgs(new VpnState(VpnStatus.Disconnected), VpnError.None,
false));
ApiHostProvider sut = new(_appSettings, _config, _vpnStatusNotifier);
RaiseVpnStatusEvent(VpnStatus.Disconnected);

// Assert
sut.GetHost().Should().Be(PROXY_HOST);
Expand All @@ -120,10 +119,15 @@ public void ItShouldReturnApiHostWhenProxyIsDisabled()
_config.Urls.ApiUrl = API_URL;
_appSettings.ActiveAlternativeApiBaseUrl.Returns(PROXY_HOST);
_appSettings.DoHEnabled.Returns(false);
ApiHostProvider sut = new(_appSettings, _config);
ApiHostProvider sut = new(_appSettings, _config, _vpnStatusNotifier);

// Assert
sut.GetHost().Should().Be(API_HOST);
}

private void RaiseVpnStatusEvent(VpnStatus status)
{
_vpnStatusNotifier.VpnStatusChanged += Raise.Event<EventHandler<VpnStatus>>(this, status);
}
}
}
Loading

0 comments on commit 9ef8b62

Please sign in to comment.