summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ios/MullvadREST/ApiHandlers/APIAvailabilityTestRequest.swift55
-rw-r--r--ios/MullvadREST/ApiHandlers/HTTP.swift1
-rw-r--r--ios/MullvadREST/Transport/ProxyConfigurationTransportProvider.swift58
-rw-r--r--ios/MullvadREST/Transport/RESTTransportProvider.swift1
-rw-r--r--ios/MullvadRESTTests/HeadRequestTests.swift40
-rw-r--r--ios/MullvadRESTTests/Mocks/RESTTransportStub.swift27
-rw-r--r--ios/MullvadRESTTests/RequestExecutorTests.swift6
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj16
-rw-r--r--ios/MullvadVPN/AccessMethodRepository/ProxyConfigurationTester.swift35
-rw-r--r--ios/MullvadVPN/AppDelegate.swift19
-rw-r--r--ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift11
-rw-r--r--ios/MullvadVPN/Coordinators/Settings/APIAccess/Edit/EditAccessMethodCoordinator.swift4
-rw-r--r--ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodCoordinator.swift6
-rw-r--r--ios/MullvadVPN/Coordinators/Settings/SettingsCoordinator.swift8
-rw-r--r--ios/MullvadVPN/SceneDelegate.swift3
15 files changed, 259 insertions, 31 deletions
diff --git a/ios/MullvadREST/ApiHandlers/APIAvailabilityTestRequest.swift b/ios/MullvadREST/ApiHandlers/APIAvailabilityTestRequest.swift
new file mode 100644
index 0000000000..03c180c349
--- /dev/null
+++ b/ios/MullvadREST/ApiHandlers/APIAvailabilityTestRequest.swift
@@ -0,0 +1,55 @@
+//
+// APIAvailabilityTestRequest.swift
+// MullvadREST
+//
+// Created by Marco Nikic on 2024-01-08.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import MullvadTypes
+
+extension REST {
+ public struct APIAvailabilityTestRequest {
+ let transport: RESTTransport
+
+ public init(transport: RESTTransport) {
+ self.transport = transport
+ }
+
+ /// Executes an HTTP `HEAD` request to the "api-addrs" endpoint.
+ ///
+ /// - Parameter completion: Completes with `nil` if the request was successful, and `Error` otherwise.
+ /// - Returns: A cancellable token to cancel the request inflight.
+ public func makeRequest(completion: @escaping (Swift.Error?) -> Void) -> Cancellable {
+ do {
+ let factory = RequestFactory(
+ hostname: defaultAPIHostname,
+ pathPrefix: "/app/v1",
+ networkTimeout: defaultAPINetworkTimeout,
+ bodyEncoder: JSONEncoder()
+ )
+ var request = try factory.createRequest(
+ endpoint: defaultAPIEndpoint,
+ method: .head,
+ pathTemplate: "api-addrs"
+ )
+ request.urlRequest.cachePolicy = .reloadIgnoringLocalCacheData
+
+ return transport.sendRequest(request.urlRequest) { _, response, error in
+ // Any response in the form of `HTTPURLResponse` means that the API was reached successfully
+ // and implying an HTTP server is running, therefore the test is considered successful.
+ guard response is HTTPURLResponse else {
+ completion(error)
+ return
+ }
+ completion(nil)
+ }
+
+ } catch {
+ completion(error)
+ }
+ return AnyCancellable()
+ }
+ }
+}
diff --git a/ios/MullvadREST/ApiHandlers/HTTP.swift b/ios/MullvadREST/ApiHandlers/HTTP.swift
index 93074fdbd3..8a14e957d1 100644
--- a/ios/MullvadREST/ApiHandlers/HTTP.swift
+++ b/ios/MullvadREST/ApiHandlers/HTTP.swift
@@ -14,6 +14,7 @@ struct HTTPMethod: RawRepresentable {
static let post = HTTPMethod(rawValue: "POST")
static let delete = HTTPMethod(rawValue: "DELETE")
static let put = HTTPMethod(rawValue: "PUT")
+ static let head = HTTPMethod(rawValue: "HEAD")
let rawValue: String
init(rawValue: String) {
diff --git a/ios/MullvadREST/Transport/ProxyConfigurationTransportProvider.swift b/ios/MullvadREST/Transport/ProxyConfigurationTransportProvider.swift
new file mode 100644
index 0000000000..356b9c1b19
--- /dev/null
+++ b/ios/MullvadREST/Transport/ProxyConfigurationTransportProvider.swift
@@ -0,0 +1,58 @@
+//
+// ProxyConfigurationTransportProvider.swift
+// MullvadREST
+//
+// Created by Marco Nikic on 2024-01-19.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import MullvadSettings
+import MullvadTypes
+
+/// Allows the creation of `RESTTransport` objects that bypass the network routing logic provided by `TransportProvider`.
+public class ProxyConfigurationTransportProvider {
+ private let shadowsocksLoader: ShadowsocksLoaderProtocol
+ private let addressCache: REST.AddressCache
+
+ public init(shadowsocksLoader: ShadowsocksLoaderProtocol, addressCache: REST.AddressCache) {
+ self.shadowsocksLoader = shadowsocksLoader
+ self.addressCache = addressCache
+ }
+
+ public func makeTransport(with configuration: PersistentProxyConfiguration) throws -> RESTTransport {
+ let urlSession = REST.makeURLSession()
+ switch configuration {
+ case .direct:
+ return URLSessionTransport(urlSession: urlSession)
+ case .bridges:
+ let shadowsocksConfiguration = try shadowsocksLoader.load()
+ return ShadowsocksTransport(
+ urlSession: urlSession,
+ configuration: shadowsocksConfiguration,
+ addressCache: addressCache
+ )
+ case let .shadowsocks(shadowSocksConfiguration):
+ return ShadowsocksTransport(
+ urlSession: urlSession,
+ configuration: ShadowsocksConfiguration(
+ address: shadowSocksConfiguration.server,
+ port: shadowSocksConfiguration.port,
+ password: shadowSocksConfiguration.password,
+ cipher: shadowSocksConfiguration.cipher.rawValue.description
+ ),
+ addressCache: addressCache
+ )
+ case let .socks5(socksConfiguration):
+ return URLSessionSocks5Transport(
+ urlSession: urlSession,
+ configuration: Socks5Configuration(
+ proxyEndpoint: socksConfiguration.toAnyIPEndpoint,
+ username: socksConfiguration.credential?.username,
+ password: socksConfiguration.credential?.password
+ ),
+ addressCache: addressCache
+ )
+ }
+ }
+}
diff --git a/ios/MullvadREST/Transport/RESTTransportProvider.swift b/ios/MullvadREST/Transport/RESTTransportProvider.swift
index 5476338ece..33e661bc9c 100644
--- a/ios/MullvadREST/Transport/RESTTransportProvider.swift
+++ b/ios/MullvadREST/Transport/RESTTransportProvider.swift
@@ -7,6 +7,7 @@
//
import Foundation
+import MullvadSettings
public protocol RESTTransportProvider {
func makeTransport() -> RESTTransport?
diff --git a/ios/MullvadRESTTests/HeadRequestTests.swift b/ios/MullvadRESTTests/HeadRequestTests.swift
new file mode 100644
index 0000000000..e5424538db
--- /dev/null
+++ b/ios/MullvadRESTTests/HeadRequestTests.swift
@@ -0,0 +1,40 @@
+//
+// HeadRequestTests.swift
+// MullvadRESTTests
+//
+// Created by Marco Nikic on 2024-01-22.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+@testable import MullvadREST
+import XCTest
+
+class HeadRequestTests: XCTestCase {
+ func testSuccessfulRequestHasNoError() throws {
+ let transport = RESTTransportStub(data: Data(), response: HTTPURLResponse())
+ let request = REST.APIAvailabilityTestRequest(transport: transport)
+
+ let successfulRequestExpectation = expectation(description: "HEAD request completed")
+ _ = request.makeRequest { error in
+ if error == nil {
+ successfulRequestExpectation.fulfill()
+ }
+ }
+
+ wait(for: [successfulRequestExpectation], timeout: 1)
+ }
+
+ func testRequestWithErrors() throws {
+ let transport = RESTTransportStub(error: URLError(.timedOut))
+ let request = REST.APIAvailabilityTestRequest(transport: transport)
+
+ let failedRequestExpectation = expectation(description: "HEAD request failed")
+ _ = request.makeRequest { error in
+ if error != nil {
+ failedRequestExpectation.fulfill()
+ }
+ }
+
+ wait(for: [failedRequestExpectation], timeout: 1)
+ }
+}
diff --git a/ios/MullvadRESTTests/Mocks/RESTTransportStub.swift b/ios/MullvadRESTTests/Mocks/RESTTransportStub.swift
new file mode 100644
index 0000000000..5e0915554b
--- /dev/null
+++ b/ios/MullvadRESTTests/Mocks/RESTTransportStub.swift
@@ -0,0 +1,27 @@
+//
+// RESTTransportStub.swift
+// MullvadRESTTests
+//
+// Created by Marco Nikic on 2024-01-22.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+@testable import MullvadREST
+@testable import MullvadTypes
+import XCTest
+
+struct RESTTransportStub: RESTTransport {
+ let name = "transport-stub"
+
+ var data: Data?
+ var response: URLResponse?
+ var error: Error?
+
+ func sendRequest(
+ _ request: URLRequest,
+ completion: @escaping (Data?, URLResponse?, Error?) -> Void
+ ) -> Cancellable {
+ completion(data, response, error)
+ return AnyCancellable()
+ }
+}
diff --git a/ios/MullvadRESTTests/RequestExecutorTests.swift b/ios/MullvadRESTTests/RequestExecutorTests.swift
index e4ca6b9537..d257007f83 100644
--- a/ios/MullvadRESTTests/RequestExecutorTests.swift
+++ b/ios/MullvadRESTTests/RequestExecutorTests.swift
@@ -7,7 +7,7 @@
//
@testable import MullvadREST
-import MullvadTypes
+@testable import MullvadTypes
import XCTest
final class RequestExecutorTests: XCTestCase {
@@ -18,8 +18,8 @@ final class RequestExecutorTests: XCTestCase {
super.setUp()
let transportProvider = REST.AnyTransportProvider {
- return AnyTransport {
- return Response(delay: 1, statusCode: 200, value: TimeResponse(dateTime: Date()))
+ AnyTransport {
+ Response(delay: 1, statusCode: 200, value: TimeResponse(dateTime: Date()))
}
}
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 0e6a5225cb..b8ee9d98a5 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -611,6 +611,10 @@
A917352129FAAA5200D5DCFD /* TransportStrategyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A917352029FAAA5200D5DCFD /* TransportStrategyTests.swift */; };
A91D78E32B03BDF200FCD5D3 /* TunnelObfuscation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5840231F2A406BF5007B27AC /* TunnelObfuscation.framework */; };
A91D78E42B03C01600FCD5D3 /* MullvadSettings.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 58B2FDD32AA71D2A003EB5C6 /* MullvadSettings.framework */; };
+ A932D9EF2B5ADD0700999395 /* ProxyConfigurationTransportProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A932D9EE2B5ADD0700999395 /* ProxyConfigurationTransportProvider.swift */; };
+ A932D9F32B5EB61100999395 /* HeadRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A932D9F22B5EB61100999395 /* HeadRequestTests.swift */; };
+ A932D9F52B5EBB9D00999395 /* RESTTransportStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = A932D9F42B5EBB9D00999395 /* RESTTransportStub.swift */; };
+ A935594C2B4C2DA900D5D524 /* APIAvailabilityTestRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A935594B2B4C2DA900D5D524 /* APIAvailabilityTestRequest.swift */; };
A94D691A2ABAD66700413DD4 /* WireGuardKitTypes in Frameworks */ = {isa = PBXBuildFile; productRef = 58FE25E22AA72AE9003D1918 /* WireGuardKitTypes */; };
A94D691B2ABAD66700413DD4 /* WireGuardKitTypes in Frameworks */ = {isa = PBXBuildFile; productRef = 58FE25E72AA7399D003D1918 /* WireGuardKitTypes */; };
A970C89D2B29E38C000A7684 /* Socks5UsernamePasswordCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = A970C89C2B29E38C000A7684 /* Socks5UsernamePasswordCommand.swift */; };
@@ -1773,6 +1777,10 @@
A92ECC232A7802520052F1B1 /* StoredAccountData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoredAccountData.swift; sourceTree = "<group>"; };
A92ECC272A7802AB0052F1B1 /* StoredDeviceData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoredDeviceData.swift; sourceTree = "<group>"; };
A92ECC2B2A7803A50052F1B1 /* DeviceState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceState.swift; sourceTree = "<group>"; };
+ A932D9EE2B5ADD0700999395 /* ProxyConfigurationTransportProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxyConfigurationTransportProvider.swift; sourceTree = "<group>"; };
+ A932D9F22B5EB61100999395 /* HeadRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadRequestTests.swift; sourceTree = "<group>"; };
+ A932D9F42B5EBB9D00999395 /* RESTTransportStub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RESTTransportStub.swift; sourceTree = "<group>"; };
+ A935594B2B4C2DA900D5D524 /* APIAvailabilityTestRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIAvailabilityTestRequest.swift; sourceTree = "<group>"; };
A935594D2B4E919F00D5D524 /* Api.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Api.xcconfig; sourceTree = "<group>"; };
A9467E7E2A29DEFE000DC21F /* RelayCacheTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayCacheTests.swift; sourceTree = "<group>"; };
A970C89C2B29E38C000A7684 /* Socks5UsernamePasswordCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Socks5UsernamePasswordCommand.swift; sourceTree = "<group>"; };
@@ -2834,6 +2842,7 @@
children = (
58BDEB982A98F4ED00F578F2 /* AnyTransport.swift */,
58BDEB9C2A98F69E00F578F2 /* MemoryCache.swift */,
+ A932D9F42B5EBB9D00999395 /* RESTTransportStub.swift */,
58BDEB9A2A98F58600F578F2 /* TimeServerProxy.swift */,
);
path = Mocks;
@@ -3248,6 +3257,7 @@
children = (
F0164EB92B4456D30020268D /* AccessMethodRepositoryStub.swift */,
58FBFBE8291622580020E046 /* ExponentialBackoffTests.swift */,
+ A932D9F22B5EB61100999395 /* HeadRequestTests.swift */,
58BDEB9E2A98F6B400F578F2 /* Mocks */,
58B4656F2A98C53300467203 /* RequestExecutorTests.swift */,
F0164EC22B4C49D30020268D /* ShadowsocksLoaderStub.swift */,
@@ -3409,6 +3419,7 @@
isa = PBXGroup;
children = (
06AC114128F8413A0037AF9A /* AddressCache.swift */,
+ A935594B2B4C2DA900D5D524 /* APIAvailabilityTestRequest.swift */,
06FAE67128F83CA40033DD93 /* HTTP.swift */,
06FAE67228F83CA40033DD93 /* RESTAccessTokenManager.swift */,
06FAE66828F83CA30033DD93 /* RESTAccountsProxy.swift */,
@@ -3459,6 +3470,7 @@
isa = PBXGroup;
children = (
F0164ED02B4F2DCB0020268D /* AccessMethodIterator.swift */,
+ A932D9EE2B5ADD0700999395 /* ProxyConfigurationTransportProvider.swift */,
F0DC77A32B2315800087F09D /* Direct */,
F0164EC02B4C03980020268D /* LastReachableApiAccessCache.swift */,
06FAE67D28F83CA50033DD93 /* RESTTransport.swift */,
@@ -4391,6 +4403,7 @@
files = (
F05F39982B21C73C006E60A7 /* CachedRelays.swift in Sources */,
F05F39972B21C735006E60A7 /* RelayCache.swift in Sources */,
+ A932D9EF2B5ADD0700999395 /* ProxyConfigurationTransportProvider.swift in Sources */,
06799AE728F98E4800ACD94E /* RESTURLSession.swift in Sources */,
A90763B52B2857D50045ADF0 /* Socks5Constants.swift in Sources */,
A90763BA2B2857D50045ADF0 /* Socks5Error.swift in Sources */,
@@ -4449,6 +4462,7 @@
06799ADF28F98E4800ACD94E /* RESTDevicesProxy.swift in Sources */,
06799ADA28F98E4800ACD94E /* RESTResponseHandler.swift in Sources */,
062B45BC28FD8C3B00746E77 /* RESTDefaults.swift in Sources */,
+ A935594C2B4C2DA900D5D524 /* APIAvailabilityTestRequest.swift in Sources */,
A90763C32B2858630045ADF0 /* Socks5Configuration.swift in Sources */,
06799AE428F98E4800ACD94E /* RESTAccountsProxy.swift in Sources */,
5897F1742913EAF800AF5695 /* ExponentialBackoff.swift in Sources */,
@@ -5185,7 +5199,9 @@
F0164EC32B4C49D30020268D /* ShadowsocksLoaderStub.swift in Sources */,
58BDEB9D2A98F69E00F578F2 /* MemoryCache.swift in Sources */,
58BDEB9B2A98F58600F578F2 /* TimeServerProxy.swift in Sources */,
+ A932D9F52B5EBB9D00999395 /* RESTTransportStub.swift in Sources */,
58BDEB992A98F4ED00F578F2 /* AnyTransport.swift in Sources */,
+ A932D9F32B5EB61100999395 /* HeadRequestTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/ios/MullvadVPN/AccessMethodRepository/ProxyConfigurationTester.swift b/ios/MullvadVPN/AccessMethodRepository/ProxyConfigurationTester.swift
index 95f6b302f7..03e108968a 100644
--- a/ios/MullvadVPN/AccessMethodRepository/ProxyConfigurationTester.swift
+++ b/ios/MullvadVPN/AccessMethodRepository/ProxyConfigurationTester.swift
@@ -8,31 +8,38 @@
import Combine
import Foundation
+import MullvadREST
import MullvadSettings
+import MullvadTypes
/// A concrete implementation of an access method proxy configuration.
class ProxyConfigurationTester: ProxyConfigurationTesterProtocol {
- private var cancellable: Cancellable?
+ private var cancellable: MullvadTypes.Cancellable?
+ private let transportProvider: ProxyConfigurationTransportProvider
+ private var headRequest: REST.APIAvailabilityTestRequest?
- static let shared = ProxyConfigurationTester()
-
- init() {}
+ init(transportProvider: ProxyConfigurationTransportProvider) {
+ self.transportProvider = transportProvider
+ }
func start(configuration: PersistentProxyConfiguration, completion: @escaping (Error?) -> Void) {
- let workItem = DispatchWorkItem {
- let randomResult = (0 ... 255).randomElement()?.isMultiple(of: 2) ?? true
-
- completion(randomResult ? nil : URLError(.timedOut))
- }
-
- DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2), execute: workItem)
-
- cancellable = AnyCancellable {
- workItem.cancel()
+ do {
+ let transport = try transportProvider.makeTransport(with: configuration)
+ let request = REST.APIAvailabilityTestRequest(transport: transport)
+ headRequest = request
+ cancellable = request.makeRequest { error in
+ DispatchQueue.main.async {
+ completion(error)
+ }
+ }
+ } catch {
+ completion(error)
}
}
func cancel() {
+ cancellable?.cancel()
cancellable = nil
+ headRequest = nil
}
}
diff --git a/ios/MullvadVPN/AppDelegate.swift b/ios/MullvadVPN/AppDelegate.swift
index 8a49c19fef..fba6e13391 100644
--- a/ios/MullvadVPN/AppDelegate.swift
+++ b/ios/MullvadVPN/AppDelegate.swift
@@ -43,6 +43,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
private let migrationManager = MigrationManager()
private(set) var accessMethodRepository = AccessMethodRepository()
+ private(set) var shadowsocksLoader: ShadowsocksLoaderProtocol!
+ private(set) var configuredTransportProvider: ProxyConfigurationTransportProvider!
// MARK: - Application lifecycle
@@ -94,14 +96,21 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
// This init cannot fail as long as the security group identifier is valid
let sharedUserDefaults = UserDefaults(suiteName: ApplicationConfiguration.securityGroupIdentifier)!
+ shadowsocksLoader = ShadowsocksLoader(
+ shadowsocksCache: shadowsocksCache,
+ relayCache: relayCache,
+ constraintsUpdater: constraintsUpdater
+ )
+
+ configuredTransportProvider = ProxyConfigurationTransportProvider(
+ shadowsocksLoader: shadowsocksLoader,
+ addressCache: addressCache
+ )
+
let transportStrategy = TransportStrategy(
sharedUserDefaults,
datasource: accessMethodRepository,
- shadowsocksLoader: ShadowsocksLoader(
- shadowsocksCache: shadowsocksCache,
- relayCache: relayCache,
- constraintsUpdater: constraintsUpdater
- )
+ shadowsocksLoader: shadowsocksLoader
)
let transportProvider = TransportProvider(
diff --git a/ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift b/ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift
index c56c376721..719c97066a 100644
--- a/ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift
+++ b/ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift
@@ -78,6 +78,7 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo
private var appPreferences: AppPreferencesDataSource
private var outgoingConnectionService: OutgoingConnectionServiceHandling
private var accessMethodRepository: AccessMethodRepositoryProtocol
+ private let configuredTransportProvider: ProxyConfigurationTransportProvider
private var outOfTimeTimer: Timer?
@@ -94,7 +95,8 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo
accountsProxy: RESTAccountHandling,
outgoingConnectionService: OutgoingConnectionServiceHandling,
appPreferences: AppPreferencesDataSource,
- accessMethodRepository: AccessMethodRepositoryProtocol
+ accessMethodRepository: AccessMethodRepositoryProtocol,
+ transportProvider: ProxyConfigurationTransportProvider
) {
self.tunnelManager = tunnelManager
self.storePaymentManager = storePaymentManager
@@ -105,6 +107,7 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo
self.appPreferences = appPreferences
self.outgoingConnectionService = outgoingConnectionService
self.accessMethodRepository = accessMethodRepository
+ self.configuredTransportProvider = transportProvider
super.init()
@@ -758,10 +761,14 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo
)
let navigationController = CustomNavigationController()
+
+ let configurationTester = ProxyConfigurationTester(transportProvider: configuredTransportProvider)
+
let coordinator = SettingsCoordinator(
navigationController: navigationController,
interactorFactory: interactorFactory,
- accessMethodRepository: accessMethodRepository
+ accessMethodRepository: accessMethodRepository,
+ proxyConfigurationTester: configurationTester
)
coordinator.didFinish = { [weak self] _ in
diff --git a/ios/MullvadVPN/Coordinators/Settings/APIAccess/Edit/EditAccessMethodCoordinator.swift b/ios/MullvadVPN/Coordinators/Settings/APIAccess/Edit/EditAccessMethodCoordinator.swift
index 237b3f1ea2..4e7d5c17b7 100644
--- a/ios/MullvadVPN/Coordinators/Settings/APIAccess/Edit/EditAccessMethodCoordinator.swift
+++ b/ios/MullvadVPN/Coordinators/Settings/APIAccess/Edit/EditAccessMethodCoordinator.swift
@@ -15,7 +15,7 @@ class EditAccessMethodCoordinator: Coordinator {
let navigationController: UINavigationController
let subject: CurrentValueSubject<AccessMethodViewModel, Never> = .init(AccessMethodViewModel())
let accessMethodRepo: AccessMethodRepositoryProtocol
- let proxyConfigurationTester: ProxyConfigurationTester
+ let proxyConfigurationTester: ProxyConfigurationTesterProtocol
let methodIdentifier: UUID
var onFinish: ((EditAccessMethodCoordinator) -> Void)?
@@ -23,7 +23,7 @@ class EditAccessMethodCoordinator: Coordinator {
init(
navigationController: UINavigationController,
accessMethodRepo: AccessMethodRepositoryProtocol,
- proxyConfigurationTester: ProxyConfigurationTester,
+ proxyConfigurationTester: ProxyConfigurationTesterProtocol,
methodIdentifier: UUID
) {
self.navigationController = navigationController
diff --git a/ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodCoordinator.swift b/ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodCoordinator.swift
index c355343d2c..0cfa2d5089 100644
--- a/ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodCoordinator.swift
+++ b/ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodCoordinator.swift
@@ -13,7 +13,7 @@ import UIKit
class ListAccessMethodCoordinator: Coordinator, Presenting, SettingsChildCoordinator {
let navigationController: UINavigationController
let accessMethodRepository: AccessMethodRepositoryProtocol
- let proxyConfigurationTester: ProxyConfigurationTester = .shared
+ let proxyConfigurationTester: ProxyConfigurationTesterProtocol
var presentationContext: UIViewController {
navigationController
@@ -21,10 +21,12 @@ class ListAccessMethodCoordinator: Coordinator, Presenting, SettingsChildCoordin
init(
navigationController: UINavigationController,
- accessMethodRepository: AccessMethodRepositoryProtocol
+ accessMethodRepository: AccessMethodRepositoryProtocol,
+ proxyConfigurationTester: ProxyConfigurationTesterProtocol
) {
self.navigationController = navigationController
self.accessMethodRepository = accessMethodRepository
+ self.proxyConfigurationTester = proxyConfigurationTester
}
func start(animated: Bool) {
diff --git a/ios/MullvadVPN/Coordinators/Settings/SettingsCoordinator.swift b/ios/MullvadVPN/Coordinators/Settings/SettingsCoordinator.swift
index 06178b93e9..b2d7d3dfc6 100644
--- a/ios/MullvadVPN/Coordinators/Settings/SettingsCoordinator.swift
+++ b/ios/MullvadVPN/Coordinators/Settings/SettingsCoordinator.swift
@@ -42,6 +42,7 @@ final class SettingsCoordinator: Coordinator, Presentable, Presenting, SettingsV
private var currentRoute: SettingsNavigationRoute?
private var modalRoute: SettingsNavigationRoute?
private let accessMethodRepository: AccessMethodRepositoryProtocol
+ private let proxyConfigurationTester: ProxyConfigurationTesterProtocol
let navigationController: UINavigationController
@@ -66,11 +67,13 @@ final class SettingsCoordinator: Coordinator, Presentable, Presenting, SettingsV
init(
navigationController: UINavigationController,
interactorFactory: SettingsInteractorFactory,
- accessMethodRepository: AccessMethodRepositoryProtocol
+ accessMethodRepository: AccessMethodRepositoryProtocol,
+ proxyConfigurationTester: ProxyConfigurationTesterProtocol
) {
self.navigationController = navigationController
self.interactorFactory = interactorFactory
self.accessMethodRepository = accessMethodRepository
+ self.proxyConfigurationTester = proxyConfigurationTester
}
/// Start the coordinator fllow.
@@ -255,7 +258,8 @@ final class SettingsCoordinator: Coordinator, Presentable, Presenting, SettingsV
case .apiAccess:
return .childCoordinator(ListAccessMethodCoordinator(
navigationController: navigationController,
- accessMethodRepository: accessMethodRepository
+ accessMethodRepository: accessMethodRepository,
+ proxyConfigurationTester: proxyConfigurationTester
))
case .ipOverride:
diff --git a/ios/MullvadVPN/SceneDelegate.swift b/ios/MullvadVPN/SceneDelegate.swift
index cb7347c9e6..c65b098814 100644
--- a/ios/MullvadVPN/SceneDelegate.swift
+++ b/ios/MullvadVPN/SceneDelegate.swift
@@ -76,7 +76,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, SettingsMigrationUIHand
outgoingConnectionProxy: OutgoingConnectionProxy(urlSession: URLSession(configuration: .ephemeral))
),
appPreferences: AppPreferences(),
- accessMethodRepository: accessMethodRepository
+ accessMethodRepository: accessMethodRepository,
+ transportProvider: appDelegate.configuredTransportProvider
)
appCoordinator?.onShowSettings = { [weak self] in