From ad58fccb772f07b259999fa423762a71f5814e27 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 21 Apr 2023 15:20:13 -0400 Subject: [PATCH 1/6] Adding Transport Protocol entry cell for Settings VPN item --- Sources/BraveStrings/BraveStrings.swift | 12 +-- .../BraveVPNSettingsViewController.swift | 87 +++++++++++++------ 2 files changed, 68 insertions(+), 31 deletions(-) diff --git a/Sources/BraveStrings/BraveStrings.swift b/Sources/BraveStrings/BraveStrings.swift index 705e78fc031..50adf001e40 100644 --- a/Sources/BraveStrings/BraveStrings.swift +++ b/Sources/BraveStrings/BraveStrings.swift @@ -2587,18 +2587,18 @@ extension Strings { public static let settingsServerLocation = NSLocalizedString("vpn.settingsServerLocation", tableName: "BraveShared", bundle: .module, value: "Location", - comment: "Table cell title for vpn's server location") + comment: "Table cell title for vpn's server location and which open opens location select") public static let settingsResetConfiguration = NSLocalizedString("vpn.settingsResetConfiguration", tableName: "BraveShared", bundle: .module, value: "Reset Configuration", comment: "Button to reset VPN configuration") - public static let settingsChangeLocation = - NSLocalizedString("vpn.settingsChangeLocation", tableName: "BraveShared", bundle: .module, - value: "Change Location", - comment: "Button to change VPN server location") - + public static let settingsTransportProtocol = + NSLocalizedString("vpn.settingsTransportProtocol", tableName: "BraveShared", bundle: .module, + value: "Transport Protocol", + comment: "Table cell title for vpn's transport protocol and which open opens protocol select") + public static let settingsContactSupport = NSLocalizedString("vpn.settingsContactSupport", tableName: "BraveShared", bundle: .module, value: "Contact Technical Support", diff --git a/Sources/BraveVPN/BraveVPNSettingsViewController.swift b/Sources/BraveVPN/BraveVPNSettingsViewController.swift index a8b5b5b0979..430e148cd4a 100644 --- a/Sources/BraveVPN/BraveVPNSettingsViewController.swift +++ b/Sources/BraveVPN/BraveVPNSettingsViewController.swift @@ -28,6 +28,7 @@ public class BraveVPNSettingsViewController: TableViewController { private let serverSectionId = "server" private let hostCellId = "host" private let locationCellId = "location" + private let protocolCellId = "protocol" private let resetCellId = "reset" private let vpnStatusSectionCellId = "vpnStatus" @@ -132,34 +133,49 @@ public class BraveVPNSettingsViewController: TableViewController { footer: .title(Strings.VPN.settingsLinkReceiptFooter)) let location = BraveVPN.serverLocation ?? "-" + let transportProtocol = "WireGuard" - let serverSection = - Section(header: .title(Strings.VPN.settingsServerSection), - rows: [Row(text: Strings.VPN.settingsServerHost, detailText: hostname, uuid: hostCellId), - Row(text: Strings.VPN.settingsServerLocation, detailText: location, - uuid: locationCellId), - Row(text: Strings.VPN.settingsChangeLocation, - selection: { [unowned self] in - self.selectServerTapped() - }, - cellClass: ButtonCell.self), - Row(text: Strings.VPN.settingsResetConfiguration, - selection: { [unowned self] in - self.resetConfigurationTapped() - }, - cellClass: ButtonCell.self, uuid: resetCellId)], - uuid: serverSectionId) + let serverSection = Section( + header: .title(Strings.VPN.settingsServerSection), + rows: [Row(text: Strings.VPN.settingsServerHost, detailText: hostname, uuid: hostCellId), + Row(text: Strings.VPN.settingsServerLocation, + detailText: location, + selection: { [unowned self] in + self.selectServerTapped() + }, + accessory: .disclosureIndicator, + cellClass: ButtonCellValue1.self, + uuid: locationCellId), + Row(text: Strings.VPN.settingsTransportProtocol, + detailText: transportProtocol, + selection: { [unowned self] in + self.selectProtocolTapped() + }, + accessory: .disclosureIndicator, + cellClass: ButtonCellValue1.self, + uuid: protocolCellId), + Row(text: Strings.VPN.settingsResetConfiguration, + selection: { [unowned self] in + self.resetConfigurationTapped() + }, + cellClass: ButtonCell.self, uuid: resetCellId)], + uuid: serverSectionId) - let techSupportSection = Section(rows: - [Row(text: Strings.VPN.settingsContactSupport, selection: { [unowned self] in - self.sendContactSupportEmail() - }, accessory: .disclosureIndicator, cellClass: ButtonCell.self)]) + let techSupportSection = Section( + rows: [Row(text: Strings.VPN.settingsContactSupport, + selection: { [unowned self] in + self.sendContactSupportEmail() + }, + accessory: .disclosureIndicator, + cellClass: ButtonCell.self)]) - let termsSection = Section(rows: - [Row(text: Strings.VPN.settingsFAQ, selection: { [unowned self] in - self.openURL?(.brave.braveVPNFaq) - - }, accessory: .disclosureIndicator, cellClass: ButtonCell.self)]) + let termsSection = Section( + rows: [Row(text: Strings.VPN.settingsFAQ, + selection: { [unowned self] in + self.openURL?(.brave.braveVPNFaq) + }, + accessory: .disclosureIndicator, + cellClass: ButtonCell.self)]) dataSource.sections = [vpnStatusSection, subscriptionSection, @@ -271,6 +287,11 @@ public class BraveVPNSettingsViewController: TableViewController { let vc = BraveVPNRegionPickerViewController() navigationController?.pushViewController(vc, animated: true) } + + private func selectProtocolTapped() { + let vc = BraveVPNRegionPickerViewController() + navigationController?.pushViewController(vc, animated: true) + } private func showVPNResetErrorAlert() { let alert = UIAlertController(title: Strings.VPN.resetVPNErrorTitle, @@ -286,3 +307,19 @@ public class BraveVPNSettingsViewController: TableViewController { vpnConnectionStatusSwitch?.isOn = BraveVPN.isConnected } } + +private class ButtonCellValue1: UITableViewCell, Cell { + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: .value1, reuseIdentifier: reuseIdentifier) + tintColorDidChange() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func tintColorDidChange() { + super.tintColorDidChange() + textLabel?.textColor = tintColor + } +} From 41c475b44dd5b47c4a11e81724408a763f34861b Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 21 Apr 2023 16:11:15 -0400 Subject: [PATCH 2/6] Desired Cell presentation show cases --- .../BraveVPNSettingsViewController.swift | 22 +------------------ 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/Sources/BraveVPN/BraveVPNSettingsViewController.swift b/Sources/BraveVPN/BraveVPNSettingsViewController.swift index 430e148cd4a..20371712a11 100644 --- a/Sources/BraveVPN/BraveVPNSettingsViewController.swift +++ b/Sources/BraveVPN/BraveVPNSettingsViewController.swift @@ -144,7 +144,6 @@ public class BraveVPNSettingsViewController: TableViewController { self.selectServerTapped() }, accessory: .disclosureIndicator, - cellClass: ButtonCellValue1.self, uuid: locationCellId), Row(text: Strings.VPN.settingsTransportProtocol, detailText: transportProtocol, @@ -152,7 +151,6 @@ public class BraveVPNSettingsViewController: TableViewController { self.selectProtocolTapped() }, accessory: .disclosureIndicator, - cellClass: ButtonCellValue1.self, uuid: protocolCellId), Row(text: Strings.VPN.settingsResetConfiguration, selection: { [unowned self] in @@ -166,15 +164,13 @@ public class BraveVPNSettingsViewController: TableViewController { selection: { [unowned self] in self.sendContactSupportEmail() }, - accessory: .disclosureIndicator, - cellClass: ButtonCell.self)]) + accessory: .disclosureIndicator)]) let termsSection = Section( rows: [Row(text: Strings.VPN.settingsFAQ, selection: { [unowned self] in self.openURL?(.brave.braveVPNFaq) }, - accessory: .disclosureIndicator, cellClass: ButtonCell.self)]) dataSource.sections = [vpnStatusSection, @@ -307,19 +303,3 @@ public class BraveVPNSettingsViewController: TableViewController { vpnConnectionStatusSwitch?.isOn = BraveVPN.isConnected } } - -private class ButtonCellValue1: UITableViewCell, Cell { - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: .value1, reuseIdentifier: reuseIdentifier) - tintColorDidChange() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func tintColorDidChange() { - super.tintColorDidChange() - textLabel?.textColor = tintColor - } -} From d4a251e1231bc5785f312fbfba19c02b0824d035 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Mon, 24 Apr 2023 15:01:53 -0400 Subject: [PATCH 3/6] Adding Protocol picker and making changes to region picker --- .../BraveVPNPickerViewController.swift | 115 ++++++++++++++++++ ...BraveVPNProtocolPickerViewController.swift | 85 +++++++++++++ .../BraveVPNRegionPickerViewController.swift | 108 +++------------- .../BraveVPNSettingsViewController.swift | 2 +- 4 files changed, 215 insertions(+), 95 deletions(-) create mode 100644 Sources/BraveVPN/BraveVPNPickerViewController.swift create mode 100644 Sources/BraveVPN/BraveVPNProtocolPickerViewController.swift diff --git a/Sources/BraveVPN/BraveVPNPickerViewController.swift b/Sources/BraveVPN/BraveVPNPickerViewController.swift new file mode 100644 index 00000000000..6c22c13c6fe --- /dev/null +++ b/Sources/BraveVPN/BraveVPNPickerViewController.swift @@ -0,0 +1,115 @@ +// Copyright 2020 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import UIKit +import Shared +import BraveUI +import Lottie +import NetworkExtension +import GuardianConnect + +class BraveVPNPickerViewController: UIViewController { + + private var overlayView: UIView? + let tableView: UITableView = .init(frame: .zero, style: .insetGrouped) + + deinit { + NotificationCenter.default.removeObserver(self) + } + + var isLoading: Bool = false { + didSet { + overlayView?.removeFromSuperview() + + navigationItem.hidesBackButton = isLoading + + // Prevent dismissing the modal by swipe when the VPN is being configured + navigationController?.isModalInPresentation = isLoading + + if !isLoading { return } + + let overlay = UIView().then { + $0.backgroundColor = UIColor.black.withAlphaComponent(0.5) + let activityIndicator = UIActivityIndicatorView().then { indicator in + indicator.startAnimating() + indicator.autoresizingMask = [.flexibleWidth, .flexibleHeight] + } + + $0.addSubview(activityIndicator) + } + + view.addSubview(overlay) + overlay.snp.makeConstraints { + $0.edges.equalToSuperview() + } + + overlayView = overlay + } + } + + init() { + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { fatalError() } + + override func viewDidLoad() { + tableView.register(VPNRegionCell.self) + + NotificationCenter.default.addObserver(self, selector: #selector(vpnConfigChanged(notification:)), + name: .NEVPNStatusDidChange, object: nil) + + view.addSubview(tableView) + tableView.snp.makeConstraints { + $0.edges.equalToSuperview() + } + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + tableView.reloadData() + } + + @objc func vpnConfigChanged(notification: NSNotification) { + } + + func showSuccessAlert() { + let animation = AnimationView(name: "vpncheckmark", bundle: .module).then { + $0.bounds = CGRect(x: 0, y: 0, width: 300, height: 200) + $0.contentMode = .scaleAspectFill + $0.play() + } + + let popup = AlertPopupView(imageView: animation, + title: Strings.VPN.regionSwitchSuccessPopupText, message: "", + titleWeight: .semibold, titleSize: 18, + dismissHandler: { true }) + + popup.showWithType(showType: .flyUp, autoDismissTime: 1.5) + } + + func showErrorAlert(title: String, message: String?) { + let alert = AlertController(title: Strings.VPN.regionPickerErrorTitle, + message: Strings.VPN.regionPickerErrorMessage, + preferredStyle: .alert) + let okAction = UIAlertAction(title: Strings.OKString, style: .default) { _ in + self.dismiss(animated: true) + } + alert.addAction(okAction) + + present(alert, animated: true) + } +} + +class VPNRegionCell: UITableViewCell, TableViewReusable { + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: .value1, reuseIdentifier: reuseIdentifier) + } + @available(*, unavailable) + required init(coder: NSCoder) { + fatalError() + } +} diff --git a/Sources/BraveVPN/BraveVPNProtocolPickerViewController.swift b/Sources/BraveVPN/BraveVPNProtocolPickerViewController.swift new file mode 100644 index 00000000000..5ccdfb4813d --- /dev/null +++ b/Sources/BraveVPN/BraveVPNProtocolPickerViewController.swift @@ -0,0 +1,85 @@ +// Copyright 2023 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import UIKit +import Shared +import BraveUI +import Lottie +import NetworkExtension +import GuardianConnect + +class BraveVPNProtocolPickerViewController: BraveVPNPickerViewController { + + private let regionList: [GRDRegion] + + /// This group monitors vpn connection status. + private var dispatchGroup: DispatchGroup? + private var vpnRegionChangeSuccess = false + + override init() { + self.regionList = BraveVPN.regions + .sorted { $0.displayName < $1.displayName } + + super.init() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { fatalError() } + + override func viewDidLoad() { + title = "Transport Protocol" + + tableView.delegate = self + tableView.dataSource = self + + super.viewDidLoad() + } + + override func vpnConfigChanged(notification: NSNotification) { + guard let connection = notification.object as? NEVPNConnection else { return } + + if connection.status == .connected { + dispatchGroup?.leave() + self.vpnRegionChangeSuccess = true + dispatchGroup = nil + } + } +} + +// MARK: - UITableView Data Source & Delegate + +extension BraveVPNProtocolPickerViewController: UITableViewDelegate, UITableViewDataSource { + + func numberOfSections(in tableView: UITableView) -> Int { + 1 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + regionList.count + } + + func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? { + return "Please select your preferred transport protocol. Once switched your existing VPN credentials will be cleared and you will be reconnected if a VPN connection is currently established" + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(for: indexPath) as VPNRegionCell + cell.accessoryType = .none + + guard let server = regionList[safe: indexPath.row] else { return cell } + cell.textLabel?.text = server.displayName + + if server.displayName == BraveVPN.selectedRegion?.displayName { + cell.accessoryType = .checkmark + } + + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + + } +} diff --git a/Sources/BraveVPN/BraveVPNRegionPickerViewController.swift b/Sources/BraveVPN/BraveVPNRegionPickerViewController.swift index 731779cf099..0060bd5c3cb 100644 --- a/Sources/BraveVPN/BraveVPNRegionPickerViewController.swift +++ b/Sources/BraveVPN/BraveVPNRegionPickerViewController.swift @@ -10,10 +10,7 @@ import Lottie import NetworkExtension import GuardianConnect -class BraveVPNRegionPickerViewController: UIViewController { - - private var overlayView: UIView? - private let tableView: UITableView = .init(frame: .zero, style: .insetGrouped) +class BraveVPNRegionPickerViewController: BraveVPNPickerViewController { private let regionList: [GRDRegion] private enum Section: Int, CaseIterable { @@ -21,49 +18,15 @@ class BraveVPNRegionPickerViewController: UIViewController { case regionList } - deinit { - NotificationCenter.default.removeObserver(self) - } - /// This group monitors vpn connection status. private var dispatchGroup: DispatchGroup? private var vpnRegionChangeSuccess = false - private var isLoading: Bool = false { - didSet { - overlayView?.removeFromSuperview() - - navigationItem.hidesBackButton = isLoading - - // Prevent dismissing the modal by swipe when the VPN is being configured - navigationController?.isModalInPresentation = isLoading - - if !isLoading { return } - - let overlay = UIView().then { - $0.backgroundColor = UIColor.black.withAlphaComponent(0.5) - let activityIndicator = UIActivityIndicatorView().then { indicator in - indicator.startAnimating() - indicator.autoresizingMask = [.flexibleWidth, .flexibleHeight] - } - - $0.addSubview(activityIndicator) - } - - view.addSubview(overlay) - overlay.snp.makeConstraints { - $0.edges.equalToSuperview() - } - - overlayView = overlay - } - } - - init() { + override init() { self.regionList = BraveVPN.regions .sorted { $0.displayName < $1.displayName } - super.init(nibName: nil, bundle: nil) + super.init() } @available(*, unavailable) @@ -74,18 +37,11 @@ class BraveVPNRegionPickerViewController: UIViewController { tableView.delegate = self tableView.dataSource = self - tableView.register(VPNRegionCell.self) - NotificationCenter.default.addObserver(self, selector: #selector(vpnConfigChanged(notification:)), - name: .NEVPNStatusDidChange, object: nil) - - view.addSubview(tableView) - tableView.snp.makeConstraints { - $0.edges.equalToSuperview() - } + super.viewDidLoad() } - @objc private func vpnConfigChanged(notification: NSNotification) { + override func vpnConfigChanged(notification: NSNotification) { guard let connection = notification.object as? NEVPNConnection else { return } if connection.status == .connected { @@ -94,15 +50,12 @@ class BraveVPNRegionPickerViewController: UIViewController { dispatchGroup = nil } } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - tableView.reloadData() - } } // MARK: - UITableView Data Source & Delegate + extension BraveVPNRegionPickerViewController: UITableViewDelegate, UITableViewDataSource { + func numberOfSections(in tableView: UITableView) -> Int { Section.allCases.count } @@ -167,24 +120,13 @@ extension BraveVPNRegionPickerViewController: UITableViewDelegate, UITableViewDa BraveVPN.changeVPNRegion(to: newRegion) { [weak self] success in guard let self = self else { return } - func _showError() { + if !success { DispatchQueue.main.async { - let alert = AlertController(title: Strings.VPN.regionPickerErrorTitle, - message: Strings.VPN.regionPickerErrorMessage, - preferredStyle: .alert) - let okAction = UIAlertAction(title: Strings.OKString, style: .default) { _ in - self.dismiss(animated: true) - } - alert.addAction(okAction) - - self.present(alert, animated: true) + self.showErrorAlert(title: Strings.VPN.regionPickerErrorTitle, + message: Strings.VPN.regionPickerErrorMessage) } } - if !success { - _showError() - } - // Changing vpn server settings takes lot of time, // and nothing we can do about it as it relies on Apple apis. // Here we observe vpn status and we show success alert if it connected, @@ -205,34 +147,12 @@ extension BraveVPNRegionPickerViewController: UITableViewDelegate, UITableViewDa self.showSuccessAlert() } } else { - _showError() + DispatchQueue.main.async { + self.showErrorAlert(title: Strings.VPN.regionPickerErrorTitle, + message: Strings.VPN.regionPickerErrorMessage) + } } } } } - - private func showSuccessAlert() { - let animation = AnimationView(name: "vpncheckmark", bundle: .module).then { - $0.bounds = CGRect(x: 0, y: 0, width: 300, height: 200) - $0.contentMode = .scaleAspectFill - $0.play() - } - - let popup = AlertPopupView(imageView: animation, - title: Strings.VPN.regionSwitchSuccessPopupText, message: "", - titleWeight: .semibold, titleSize: 18, - dismissHandler: { true }) - - popup.showWithType(showType: .flyUp, autoDismissTime: 1.5) - } -} - -private class VPNRegionCell: UITableViewCell, TableViewReusable { - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: .value1, reuseIdentifier: reuseIdentifier) - } - @available(*, unavailable) - required init(coder: NSCoder) { - fatalError() - } } diff --git a/Sources/BraveVPN/BraveVPNSettingsViewController.swift b/Sources/BraveVPN/BraveVPNSettingsViewController.swift index 20371712a11..2ba6948f0a2 100644 --- a/Sources/BraveVPN/BraveVPNSettingsViewController.swift +++ b/Sources/BraveVPN/BraveVPNSettingsViewController.swift @@ -285,7 +285,7 @@ public class BraveVPNSettingsViewController: TableViewController { } private func selectProtocolTapped() { - let vc = BraveVPNRegionPickerViewController() + let vc = BraveVPNProtocolPickerViewController() navigationController?.pushViewController(vc, animated: true) } From a8fe4aea39c989dffdb765f2da30ed552aee9c43 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Tue, 25 Apr 2023 13:19:23 -0400 Subject: [PATCH 4/6] Adding protocol Changer to option menu for tunnel items --- Sources/BraveVPN/BraveVPN.swift | 40 ++++++++++++++-- .../BraveVPNPickerViewController.swift | 21 +++++---- ...BraveVPNProtocolPickerViewController.swift | 47 ++++++++++++++----- .../BraveVPNRegionPickerViewController.swift | 12 ++--- 4 files changed, 88 insertions(+), 32 deletions(-) diff --git a/Sources/BraveVPN/BraveVPN.swift b/Sources/BraveVPN/BraveVPN.swift index 71109f8bc65..e9f796903b1 100644 --- a/Sources/BraveVPN/BraveVPN.swift +++ b/Sources/BraveVPN/BraveVPN.swift @@ -16,6 +16,7 @@ public class BraveVPN { private static let housekeepingApi = GRDHousekeepingAPI() private static let helper = GRDVPNHelper.sharedInstance() private static let serverManager = GRDServerManager() + private static let tunnelManager = GRDTunnelManager() public static let iapObserver = IAPObserver() @@ -278,11 +279,14 @@ public class BraveVPN { completion?(status == .success) } } else { - // Setting preferred protocol in order to determine which tunnel to be activated while region selection + // Setting User preferred Transport Protocol to WireGuard + // In order to easily fetch and change in settings later GRDTransportProtocol.setUserPreferred(.wireGuard) - + // New user or no credentials and have to remake them. - helper.configureFirstTimeUser(for: .wireGuard, postCredential: nil) { success, error in + helper.configureFirstTimeUser( + for: GRDTransportProtocol.getUserPreferredTransportProtocol(), + postCredential: nil) { success, error in if let error = error { logAndStoreError("configureFirstTimeUserPostCredential \(error)") } else { @@ -308,6 +312,36 @@ public class BraveVPN { completion?(status) } } + + public static func changePreferredTransportProtocol(with transportProtocol: TransportProtocol, completion: ((Bool) -> Void)? = nil) { + helper.forceDisconnectVPNIfNecessary() + GRDVPNHelper.clearVpnConfiguration() + + GRDTransportProtocol.setUserPreferred(transportProtocol) + + // New user or no credentials and have to remake them. + helper.configureFirstTimeUser(for: transportProtocol, postCredential: nil) { success, error in + if let error = error { + logAndStoreError("Change Preferred transport FirstTimeUserPostCredential \(error)") + } else { + removeConfigurationFromPreferences(for: transportProtocol) + } + + reconnectPending = false + completion?(success) + } + + func removeConfigurationFromPreferences(for transportProtocol: TransportProtocol) { + switch transportProtocol { + case .wireGuard: + helper.ikev2VPNManager.removeFromPreferences() + case .ikEv2: + tunnelManager.removeTunnel() + default: + return + } + } + } public static func clearCredentials() { GRDKeychain.removeGuardianKeychainItems() diff --git a/Sources/BraveVPN/BraveVPNPickerViewController.swift b/Sources/BraveVPN/BraveVPNPickerViewController.swift index 6c22c13c6fe..8ab29b2828c 100644 --- a/Sources/BraveVPN/BraveVPNPickerViewController.swift +++ b/Sources/BraveVPN/BraveVPNPickerViewController.swift @@ -73,8 +73,7 @@ class BraveVPNPickerViewController: UIViewController { tableView.reloadData() } - @objc func vpnConfigChanged(notification: NSNotification) { - } + @objc func vpnConfigChanged(notification: NSNotification) { } func showSuccessAlert() { let animation = AnimationView(name: "vpncheckmark", bundle: .module).then { @@ -92,15 +91,17 @@ class BraveVPNPickerViewController: UIViewController { } func showErrorAlert(title: String, message: String?) { - let alert = AlertController(title: Strings.VPN.regionPickerErrorTitle, - message: Strings.VPN.regionPickerErrorMessage, - preferredStyle: .alert) - let okAction = UIAlertAction(title: Strings.OKString, style: .default) { _ in - self.dismiss(animated: true) + DispatchQueue.main.async { + let alert = AlertController(title: Strings.VPN.regionPickerErrorTitle, + message: Strings.VPN.regionPickerErrorMessage, + preferredStyle: .alert) + let okAction = UIAlertAction(title: Strings.OKString, style: .default) { _ in + self.dismiss(animated: true) + } + alert.addAction(okAction) + + self.present(alert, animated: true) } - alert.addAction(okAction) - - present(alert, animated: true) } } diff --git a/Sources/BraveVPN/BraveVPNProtocolPickerViewController.swift b/Sources/BraveVPN/BraveVPNProtocolPickerViewController.swift index 5ccdfb4813d..4946d7fb153 100644 --- a/Sources/BraveVPN/BraveVPNProtocolPickerViewController.swift +++ b/Sources/BraveVPN/BraveVPNProtocolPickerViewController.swift @@ -12,15 +12,14 @@ import GuardianConnect class BraveVPNProtocolPickerViewController: BraveVPNPickerViewController { - private let regionList: [GRDRegion] + private let tunnelProtocolList: [TransportProtocol] /// This group monitors vpn connection status. private var dispatchGroup: DispatchGroup? private var vpnRegionChangeSuccess = false override init() { - self.regionList = BraveVPN.regions - .sorted { $0.displayName < $1.displayName } + self.tunnelProtocolList = [.wireGuard, .ikEv2] super.init() } @@ -35,6 +34,8 @@ class BraveVPNProtocolPickerViewController: BraveVPNPickerViewController { tableView.dataSource = self super.viewDidLoad() + + print("Transport Protocol \(GRDTransportProtocol.getUserPreferredTransportProtocol())") } override func vpnConfigChanged(notification: NSNotification) { @@ -52,12 +53,8 @@ class BraveVPNProtocolPickerViewController: BraveVPNPickerViewController { extension BraveVPNProtocolPickerViewController: UITableViewDelegate, UITableViewDataSource { - func numberOfSections(in tableView: UITableView) -> Int { - 1 - } - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - regionList.count + tunnelProtocolList.count } func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? { @@ -68,10 +65,12 @@ extension BraveVPNProtocolPickerViewController: UITableViewDelegate, UITableView let cell = tableView.dequeueReusableCell(for: indexPath) as VPNRegionCell cell.accessoryType = .none - guard let server = regionList[safe: indexPath.row] else { return cell } - cell.textLabel?.text = server.displayName + guard let tunnelProtocol = tunnelProtocolList[safe: indexPath.row] else { return cell } + cell.textLabel?.text = GRDTransportProtocol.prettyTransportProtocolString(for: tunnelProtocol) + + let activeProtocolOption = GRDTransportProtocol.getUserPreferredTransportProtocol() - if server.displayName == BraveVPN.selectedRegion?.displayName { + if activeProtocolOption == tunnelProtocol { cell.accessoryType = .checkmark } @@ -81,5 +80,31 @@ extension BraveVPNProtocolPickerViewController: UITableViewDelegate, UITableView func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) + guard let tunnelProtocol = tunnelProtocolList[safe: indexPath.row] else { return } + + let activeProtocolOption = GRDTransportProtocol.getUserPreferredTransportProtocol() + + // Same option is selected do nothing + if activeProtocolOption == tunnelProtocol { + return + } + + isLoading = true + + BraveVPN.changePreferredTransportProtocol(with: tunnelProtocol) { [weak self] success in + guard let self else { return } + + isLoading = false + + if success { + self.dismiss(animated: true) { + self.showSuccessAlert() + } + } else { + self.showErrorAlert(title: "Error", + message: "Failed to change transport protocol.") + } + } + } } diff --git a/Sources/BraveVPN/BraveVPNRegionPickerViewController.swift b/Sources/BraveVPN/BraveVPNRegionPickerViewController.swift index 0060bd5c3cb..b10da979f93 100644 --- a/Sources/BraveVPN/BraveVPNRegionPickerViewController.swift +++ b/Sources/BraveVPN/BraveVPNRegionPickerViewController.swift @@ -121,10 +121,8 @@ extension BraveVPNRegionPickerViewController: UITableViewDelegate, UITableViewDa guard let self = self else { return } if !success { - DispatchQueue.main.async { - self.showErrorAlert(title: Strings.VPN.regionPickerErrorTitle, - message: Strings.VPN.regionPickerErrorMessage) - } + self.showErrorAlert(title: Strings.VPN.regionPickerErrorTitle, + message: Strings.VPN.regionPickerErrorMessage) } // Changing vpn server settings takes lot of time, @@ -147,10 +145,8 @@ extension BraveVPNRegionPickerViewController: UITableViewDelegate, UITableViewDa self.showSuccessAlert() } } else { - DispatchQueue.main.async { - self.showErrorAlert(title: Strings.VPN.regionPickerErrorTitle, - message: Strings.VPN.regionPickerErrorMessage) - } + self.showErrorAlert(title: Strings.VPN.regionPickerErrorTitle, + message: Strings.VPN.regionPickerErrorMessage) } } } From c93491c038152a970fc4c61de9a11077d4cb11d4 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Tue, 25 Apr 2023 17:10:14 -0400 Subject: [PATCH 5/6] Text VPN Tunnel localization is added to string structs --- Sources/BraveStrings/BraveStrings.swift | 25 +++++++++++++++++++ Sources/BraveVPN/BraveVPN.swift | 2 +- .../BraveVPNPickerViewController.swift | 4 +-- ...BraveVPNProtocolPickerViewController.swift | 14 +++++------ .../BraveVPNRegionPickerViewController.swift | 2 +- 5 files changed, 35 insertions(+), 12 deletions(-) diff --git a/Sources/BraveStrings/BraveStrings.swift b/Sources/BraveStrings/BraveStrings.swift index 50adf001e40..08602b824b0 100644 --- a/Sources/BraveStrings/BraveStrings.swift +++ b/Sources/BraveStrings/BraveStrings.swift @@ -2869,10 +2869,35 @@ extension Strings { value: "Failed to switch servers, please try again later.", comment: "Message for error when we fail to switch vpn server for the user") + public static let protocolPickerTitle = + NSLocalizedString("vpn.protocolPickerTitle", tableName: "BraveShared", bundle: .module, + value: "Transport Protocol", + comment: "Title for vpn tunnel protocol screen") + + public static let protocolPickerDescription = + NSLocalizedString("vpn.protocolPickerDescription", tableName: "BraveShared", bundle: .module, + value: "Please select your preferred transport protocol. Once switched your existing VPN credentials will be cleared and you will be reconnected if a VPN connection is currently established.", + comment: "Description of vpn tunnel protocol") + public static let regionSwitchSuccessPopupText = NSLocalizedString("vpn.regionSwitchSuccessPopupText", tableName: "BraveShared", bundle: .module, value: "VPN region changed.", comment: "Message that we show after successfully changing vpn region.") + + public static let protocolPickerErrorTitle = + NSLocalizedString("vpn.protocolPickerErrorTitle", tableName: "BraveShared", bundle: .module, + value: "Server Error", + comment: "Title for error when we fail to switch tunnel protocol for the user") + + public static let protocolPickerErrorMessage = + NSLocalizedString("vpn.protocolPickerErrorMessage", tableName: "BraveShared", bundle: .module, + value: "Failed to switch tunnel protocol, please try again later.", + comment: "Message for error when we fail to switch tunnel protocol for the user") + + public static let protocolSwitchSuccessPopupText = + NSLocalizedString("vpn.protocolSwitchSuccessPopupText", tableName: "BraveShared", bundle: .module, + value: "VPN Tunnel Protocol changed.", + comment: "Message that we show after successfully changing tunnel protocol.") public static let settingsFailedToFetchServerList = NSLocalizedString("vpn.settingsFailedToFetchServerList", tableName: "BraveShared", bundle: .module, diff --git a/Sources/BraveVPN/BraveVPN.swift b/Sources/BraveVPN/BraveVPN.swift index e9f796903b1..9b4f6dd55b5 100644 --- a/Sources/BraveVPN/BraveVPN.swift +++ b/Sources/BraveVPN/BraveVPN.swift @@ -282,7 +282,7 @@ public class BraveVPN { // Setting User preferred Transport Protocol to WireGuard // In order to easily fetch and change in settings later GRDTransportProtocol.setUserPreferred(.wireGuard) - + // New user or no credentials and have to remake them. helper.configureFirstTimeUser( for: GRDTransportProtocol.getUserPreferredTransportProtocol(), diff --git a/Sources/BraveVPN/BraveVPNPickerViewController.swift b/Sources/BraveVPN/BraveVPNPickerViewController.swift index 8ab29b2828c..bb33a599359 100644 --- a/Sources/BraveVPN/BraveVPNPickerViewController.swift +++ b/Sources/BraveVPN/BraveVPNPickerViewController.swift @@ -75,7 +75,7 @@ class BraveVPNPickerViewController: UIViewController { @objc func vpnConfigChanged(notification: NSNotification) { } - func showSuccessAlert() { + func showSuccessAlert(text: String) { let animation = AnimationView(name: "vpncheckmark", bundle: .module).then { $0.bounds = CGRect(x: 0, y: 0, width: 300, height: 200) $0.contentMode = .scaleAspectFill @@ -83,7 +83,7 @@ class BraveVPNPickerViewController: UIViewController { } let popup = AlertPopupView(imageView: animation, - title: Strings.VPN.regionSwitchSuccessPopupText, message: "", + title: text, message: "", titleWeight: .semibold, titleSize: 18, dismissHandler: { true }) diff --git a/Sources/BraveVPN/BraveVPNProtocolPickerViewController.swift b/Sources/BraveVPN/BraveVPNProtocolPickerViewController.swift index 4946d7fb153..a0c8872727c 100644 --- a/Sources/BraveVPN/BraveVPNProtocolPickerViewController.swift +++ b/Sources/BraveVPN/BraveVPNProtocolPickerViewController.swift @@ -28,14 +28,12 @@ class BraveVPNProtocolPickerViewController: BraveVPNPickerViewController { required init?(coder: NSCoder) { fatalError() } override func viewDidLoad() { - title = "Transport Protocol" + title = Strings.VPN.protocolPickerTitle tableView.delegate = self tableView.dataSource = self super.viewDidLoad() - - print("Transport Protocol \(GRDTransportProtocol.getUserPreferredTransportProtocol())") } override func vpnConfigChanged(notification: NSNotification) { @@ -58,7 +56,7 @@ extension BraveVPNProtocolPickerViewController: UITableViewDelegate, UITableView } func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? { - return "Please select your preferred transport protocol. Once switched your existing VPN credentials will be cleared and you will be reconnected if a VPN connection is currently established" + return Strings.VPN.protocolPickerDescription } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { @@ -94,15 +92,15 @@ extension BraveVPNProtocolPickerViewController: UITableViewDelegate, UITableView BraveVPN.changePreferredTransportProtocol(with: tunnelProtocol) { [weak self] success in guard let self else { return } - isLoading = false + self.isLoading = false if success { self.dismiss(animated: true) { - self.showSuccessAlert() + self.showSuccessAlert(text: Strings.VPN.protocolSwitchSuccessPopupText) } } else { - self.showErrorAlert(title: "Error", - message: "Failed to change transport protocol.") + self.showErrorAlert(title: Strings.VPN.protocolPickerErrorTitle, + message: Strings.VPN.protocolPickerErrorMessage) } } diff --git a/Sources/BraveVPN/BraveVPNRegionPickerViewController.swift b/Sources/BraveVPN/BraveVPNRegionPickerViewController.swift index b10da979f93..962853111c5 100644 --- a/Sources/BraveVPN/BraveVPNRegionPickerViewController.swift +++ b/Sources/BraveVPN/BraveVPNRegionPickerViewController.swift @@ -142,7 +142,7 @@ extension BraveVPNRegionPickerViewController: UITableViewDelegate, UITableViewDa if self.vpnRegionChangeSuccess { self.dismiss(animated: true) { - self.showSuccessAlert() + self.showSuccessAlert(text: Strings.VPN.regionSwitchSuccessPopupText) } } else { self.showErrorAlert(title: Strings.VPN.regionPickerErrorTitle, From b8a03c258d6e4c2a75655fd617bddde95baab2ca Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Thu, 27 Apr 2023 13:07:00 -0400 Subject: [PATCH 6/6] Adding Tunnel Protocol to Support Form and changing active text on protocol label from settings page --- .../BraveVPNContactFormViewController.swift | 28 +++++++++++++++++-- .../BraveVPNSettingsViewController.swift | 5 +++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/Sources/BraveVPN/BraveVPNContactFormViewController.swift b/Sources/BraveVPN/BraveVPNContactFormViewController.swift index 30b652b92b6..bc899a4e2a0 100644 --- a/Sources/BraveVPN/BraveVPNContactFormViewController.swift +++ b/Sources/BraveVPN/BraveVPNContactFormViewController.swift @@ -13,6 +13,7 @@ import UIKit import BraveUI import os.log import BraveStrings +import GuardianConnect class BraveVPNContactFormViewController: TableViewController { @@ -24,6 +25,7 @@ class BraveVPNContactFormViewController: TableViewController { private struct ContactForm { var hostname: String? + var tunnelProtocol: String? var subscriptionType: String? var receipt: String? var appVersion: String? @@ -75,6 +77,23 @@ class BraveVPNContactFormViewController: TableViewController { } }))) + // MARK: TunnelProtocol + let userPreferredTunnelProtocol = GRDTransportProtocol.getUserPreferredTransportProtocol() + let transportProtocol = GRDTransportProtocol.prettyTransportProtocolString(for: userPreferredTunnelProtocol) + let tunnelProtocolRow = + Row( + text: Strings.VPN.protocolPickerTitle, detailText: transportProtocol, + accessory: .view( + SwitchAccessoryView( + initialValue: false, + valueChange: { [weak self] isOn in + if isOn { + self?.contactForm.tunnelProtocol = transportProtocol + } else { + self?.contactForm.tunnelProtocol = nil + } + })), cellClass: MultilineSubtitleCell.self) + // MARK: SubscriptionType let subscriptionType = BraveVPN.subscriptionName let subscriptionTypeRow = @@ -189,8 +208,8 @@ class BraveVPNContactFormViewController: TableViewController { })), cellClass: MultilineSubtitleCell.self) var section = Section(rows: [ - hostnameRow, subscriptionTypeRow, receiptRow, appVersionRow, - timezoneRow, networkTypeRow, carrierRow, errorLogs, + hostnameRow, tunnelProtocolRow, subscriptionTypeRow, receiptRow, + appVersionRow, timezoneRow, networkTypeRow, carrierRow, errorLogs ]) // MARK: Issue @@ -280,6 +299,11 @@ class BraveVPNContactFormViewController: TableViewController { body.append(Strings.VPN.contactFormHostname) body.append("\n\(hostname)\n\n") } + + if let tunnelProtocol = contactForm.tunnelProtocol { + body.append(Strings.VPN.protocolPickerTitle) + body.append("\n\(tunnelProtocol)\n\n") + } if let subcriptionType = contactForm.subscriptionType { body.append(Strings.VPN.contactFormSubscriptionType) diff --git a/Sources/BraveVPN/BraveVPNSettingsViewController.swift b/Sources/BraveVPN/BraveVPNSettingsViewController.swift index 2ba6948f0a2..902b00af89d 100644 --- a/Sources/BraveVPN/BraveVPNSettingsViewController.swift +++ b/Sources/BraveVPN/BraveVPNSettingsViewController.swift @@ -10,6 +10,7 @@ import Preferences import BraveUI import os.log import BraveShared +import GuardianConnect public class BraveVPNSettingsViewController: TableViewController { @@ -133,8 +134,10 @@ public class BraveVPNSettingsViewController: TableViewController { footer: .title(Strings.VPN.settingsLinkReceiptFooter)) let location = BraveVPN.serverLocation ?? "-" - let transportProtocol = "WireGuard" + let userPreferredTunnelProtocol = GRDTransportProtocol.getUserPreferredTransportProtocol() + let transportProtocol = GRDTransportProtocol.prettyTransportProtocolString(for: userPreferredTunnelProtocol) + let serverSection = Section( header: .title(Strings.VPN.settingsServerSection), rows: [Row(text: Strings.VPN.settingsServerHost, detailText: hostname, uuid: hostCellId),