Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Commit

Permalink
Fix #7255: VPN Protocol (Tunnel) Option (#7334)
Browse files Browse the repository at this point in the history
  • Loading branch information
soner-yuksel authored Apr 28, 2023
1 parent d5276e8 commit 87e7718
Show file tree
Hide file tree
Showing 7 changed files with 374 additions and 131 deletions.
37 changes: 31 additions & 6 deletions Sources/BraveStrings/BraveStrings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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,
Expand Down
38 changes: 36 additions & 2 deletions Sources/BraveVPN/BraveVPN.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down Expand Up @@ -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 {
Expand All @@ -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()
Expand Down
28 changes: 26 additions & 2 deletions Sources/BraveVPN/BraveVPNContactFormViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import UIKit
import BraveUI
import os.log
import BraveStrings
import GuardianConnect

class BraveVPNContactFormViewController: TableViewController {

Expand All @@ -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?
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
116 changes: 116 additions & 0 deletions Sources/BraveVPN/BraveVPNPickerViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// 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(text: String) {
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: text, message: "",
titleWeight: .semibold, titleSize: 18,
dismissHandler: { true })

popup.showWithType(showType: .flyUp, autoDismissTime: 1.5)
}

func showErrorAlert(title: String, message: String?) {
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)
}
}
}

class VPNRegionCell: UITableViewCell, TableViewReusable {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: .value1, reuseIdentifier: reuseIdentifier)
}
@available(*, unavailable)
required init(coder: NSCoder) {
fatalError()
}
}
Loading

0 comments on commit 87e7718

Please sign in to comment.