Move processor implementations to concrete objects (#983)
Formerly via blocks, now with final classes. App: - ProfileProcessor - AppTunnelProcessor - Implemented by DefaultAppProcessor in app - Implemented by MockAppProcessor in UILibrary (for previews) Tunnel: - PacketTunnelProcessor - Implemented by DefaultTunnelProcessor
This commit is contained in:
parent
a4ebea1f95
commit
aac04c4008
|
@ -28,12 +28,10 @@ import CoreData
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
extension AppData {
|
extension AppData {
|
||||||
|
public static var cdPreferencesModel: NSManagedObjectModel {
|
||||||
@MainActor
|
|
||||||
public static let cdPreferencesModel: NSManagedObjectModel = {
|
|
||||||
guard let model: NSManagedObjectModel = .mergedModel(from: [.module]) else {
|
guard let model: NSManagedObjectModel = .mergedModel(from: [.module]) else {
|
||||||
fatalError("Unable to build Core Data model (Preferences v3)")
|
fatalError("Unable to build Core Data model (Preferences v3)")
|
||||||
}
|
}
|
||||||
return model
|
return model
|
||||||
}()
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ public final class ExtendedTunnel: ObservableObject {
|
||||||
|
|
||||||
private let environment: TunnelEnvironment
|
private let environment: TunnelEnvironment
|
||||||
|
|
||||||
private let processor: TunnelProcessor?
|
private let processor: AppTunnelProcessor?
|
||||||
|
|
||||||
private let interval: TimeInterval
|
private let interval: TimeInterval
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ public final class ExtendedTunnel: ObservableObject {
|
||||||
public init(
|
public init(
|
||||||
tunnel: Tunnel,
|
tunnel: Tunnel,
|
||||||
environment: TunnelEnvironment,
|
environment: TunnelEnvironment,
|
||||||
processor: TunnelProcessor? = nil,
|
processor: AppTunnelProcessor? = nil,
|
||||||
interval: TimeInterval
|
interval: TimeInterval
|
||||||
) {
|
) {
|
||||||
self.tunnel = tunnel
|
self.tunnel = tunnel
|
||||||
|
|
|
@ -1,93 +0,0 @@
|
||||||
//
|
|
||||||
// InAppProcessor.swift
|
|
||||||
// Passepartout
|
|
||||||
//
|
|
||||||
// Created by Davide De Rosa on 10/6/24.
|
|
||||||
// Copyright (c) 2024 Davide De Rosa. All rights reserved.
|
|
||||||
//
|
|
||||||
// https://github.com/passepartoutvpn
|
|
||||||
//
|
|
||||||
// This file is part of Passepartout.
|
|
||||||
//
|
|
||||||
// Passepartout 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.
|
|
||||||
//
|
|
||||||
// Passepartout 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 Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import PassepartoutKit
|
|
||||||
|
|
||||||
public final class InAppProcessor: ObservableObject, Sendable {
|
|
||||||
private let iapManager: IAPManager
|
|
||||||
|
|
||||||
public nonisolated let _title: (Profile) -> String
|
|
||||||
|
|
||||||
private nonisolated let _isIncluded: (IAPManager, Profile) -> Bool
|
|
||||||
|
|
||||||
private nonisolated let _preview: (Profile) -> ProfilePreview
|
|
||||||
|
|
||||||
private nonisolated let _requiredFeatures: (IAPManager, Profile) -> Set<AppFeature>?
|
|
||||||
|
|
||||||
private nonisolated let _willRebuild: (IAPManager, Profile.Builder) throws -> Profile.Builder
|
|
||||||
|
|
||||||
private nonisolated let _willInstall: (IAPManager, Profile) throws -> Profile
|
|
||||||
|
|
||||||
public init(
|
|
||||||
iapManager: IAPManager,
|
|
||||||
title: @escaping (Profile) -> String,
|
|
||||||
isIncluded: @escaping (IAPManager, Profile) -> Bool,
|
|
||||||
preview: @escaping (Profile) -> ProfilePreview,
|
|
||||||
requiredFeatures: @escaping (IAPManager, Profile) -> Set<AppFeature>?,
|
|
||||||
willRebuild: @escaping (IAPManager, Profile.Builder) throws -> Profile.Builder,
|
|
||||||
willInstall: @escaping (IAPManager, Profile) throws -> Profile
|
|
||||||
) {
|
|
||||||
self.iapManager = iapManager
|
|
||||||
_title = title
|
|
||||||
_isIncluded = isIncluded
|
|
||||||
_preview = preview
|
|
||||||
_requiredFeatures = requiredFeatures
|
|
||||||
_willRebuild = willRebuild
|
|
||||||
_willInstall = willInstall
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - ProfileProcessor
|
|
||||||
|
|
||||||
extension InAppProcessor: ProfileProcessor {
|
|
||||||
public func title(for profile: Profile) -> String {
|
|
||||||
_title(profile)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func isIncluded(_ profile: Profile) -> Bool {
|
|
||||||
_isIncluded(iapManager, profile)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func preview(from profile: Profile) -> ProfilePreview {
|
|
||||||
_preview(profile)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func requiredFeatures(_ profile: Profile) -> Set<AppFeature>? {
|
|
||||||
_requiredFeatures(iapManager, profile)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func willRebuild(_ builder: Profile.Builder) throws -> Profile.Builder {
|
|
||||||
try _willRebuild(iapManager, builder)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - TunnelProcessor
|
|
||||||
|
|
||||||
extension InAppProcessor: TunnelProcessor {
|
|
||||||
public func willInstall(_ profile: Profile) throws -> Profile {
|
|
||||||
try _willInstall(iapManager, profile)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// ProfileProcessor.swift
|
// Processors.swift
|
||||||
// Passepartout
|
// Passepartout
|
||||||
//
|
//
|
||||||
// Created by Davide De Rosa on 11/20/24.
|
// Created by Davide De Rosa on 11/20/24.
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import PassepartoutKit
|
import PassepartoutKit
|
||||||
|
|
||||||
|
@MainActor
|
||||||
public protocol ProfileProcessor {
|
public protocol ProfileProcessor {
|
||||||
func isIncluded(_ profile: Profile) -> Bool
|
func isIncluded(_ profile: Profile) -> Bool
|
||||||
|
|
||||||
|
@ -35,3 +36,14 @@ public protocol ProfileProcessor {
|
||||||
|
|
||||||
func willRebuild(_ builder: Profile.Builder) throws -> Profile.Builder
|
func willRebuild(_ builder: Profile.Builder) throws -> Profile.Builder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
public protocol AppTunnelProcessor {
|
||||||
|
func title(for profile: Profile) -> String
|
||||||
|
|
||||||
|
func willInstall(_ profile: Profile) throws -> Profile
|
||||||
|
}
|
||||||
|
|
||||||
|
public protocol PacketTunnelProcessor {
|
||||||
|
nonisolated func willStart(_ profile: Profile) throws -> Profile
|
||||||
|
}
|
|
@ -39,27 +39,7 @@ extension AppContext {
|
||||||
[]
|
[]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
let processor = InAppProcessor(
|
let processor = MockAppProcessor(iapManager: iapManager)
|
||||||
iapManager: iapManager,
|
|
||||||
title: {
|
|
||||||
"Passepartout.Mock: \($0.name)"
|
|
||||||
},
|
|
||||||
isIncluded: { _, _ in
|
|
||||||
true
|
|
||||||
},
|
|
||||||
preview: {
|
|
||||||
$0.localizedPreview
|
|
||||||
},
|
|
||||||
requiredFeatures: { _, _ in
|
|
||||||
nil
|
|
||||||
},
|
|
||||||
willRebuild: { _, builder in
|
|
||||||
builder
|
|
||||||
},
|
|
||||||
willInstall: { _, profile in
|
|
||||||
profile
|
|
||||||
}
|
|
||||||
)
|
|
||||||
let profileManager = {
|
let profileManager = {
|
||||||
let profiles: [Profile] = (0..<20)
|
let profiles: [Profile] = (0..<20)
|
||||||
.reduce(into: []) { list, _ in
|
.reduce(into: []) { list, _ in
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
//
|
||||||
|
// MockAppProcessor.swift
|
||||||
|
// Passepartout
|
||||||
|
//
|
||||||
|
// Created by Davide De Rosa on 12/8/24.
|
||||||
|
// Copyright (c) 2024 Davide De Rosa. All rights reserved.
|
||||||
|
//
|
||||||
|
// https://github.com/passepartoutvpn
|
||||||
|
//
|
||||||
|
// This file is part of Passepartout.
|
||||||
|
//
|
||||||
|
// Passepartout 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.
|
||||||
|
//
|
||||||
|
// Passepartout 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 Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
import CommonLibrary
|
||||||
|
import Foundation
|
||||||
|
import PassepartoutKit
|
||||||
|
|
||||||
|
final class MockAppProcessor {
|
||||||
|
private let iapManager: IAPManager
|
||||||
|
|
||||||
|
init(iapManager: IAPManager) {
|
||||||
|
self.iapManager = iapManager
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MockAppProcessor: ProfileProcessor {
|
||||||
|
func isIncluded(_ profile: Profile) -> Bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
func preview(from profile: Profile) -> ProfilePreview {
|
||||||
|
profile.localizedPreview
|
||||||
|
}
|
||||||
|
|
||||||
|
func requiredFeatures(_ profile: Profile) -> Set<AppFeature>? {
|
||||||
|
nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func willRebuild(_ builder: Profile.Builder) throws -> Profile.Builder {
|
||||||
|
builder
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MockAppProcessor: AppTunnelProcessor {
|
||||||
|
func title(for profile: Profile) -> String {
|
||||||
|
"Passepartout.Mock: \(profile.name)"
|
||||||
|
}
|
||||||
|
|
||||||
|
func willInstall(_ profile: Profile) throws -> Profile {
|
||||||
|
profile
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,7 +27,7 @@ import CommonLibrary
|
||||||
import Foundation
|
import Foundation
|
||||||
import PassepartoutKit
|
import PassepartoutKit
|
||||||
|
|
||||||
final class MockTunnelProcessor: TunnelProcessor {
|
final class MockTunnelProcessor: AppTunnelProcessor {
|
||||||
var titleCount = 0
|
var titleCount = 0
|
||||||
|
|
||||||
var willInstallCount = 0
|
var willInstallCount = 0
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
0E916B7C2CF811EB0072921A /* XCUIElement+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E916B7B2CF811EB0072921A /* XCUIElement+Extensions.swift */; };
|
0E916B7C2CF811EB0072921A /* XCUIElement+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E916B7B2CF811EB0072921A /* XCUIElement+Extensions.swift */; };
|
||||||
0E94EE582B93554B00588243 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7E3D672B9345FD002BBDB4 /* PacketTunnelProvider.swift */; };
|
0E94EE582B93554B00588243 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7E3D672B9345FD002BBDB4 /* PacketTunnelProvider.swift */; };
|
||||||
0EAD6A1B2CF7F79A00CC1F02 /* ScreenshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EAD6A1A2CF7F79A00CC1F02 /* ScreenshotTests.swift */; };
|
0EAD6A1B2CF7F79A00CC1F02 /* ScreenshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EAD6A1A2CF7F79A00CC1F02 /* ScreenshotTests.swift */; };
|
||||||
|
0EAEC8A92D05DB8D001AA50C /* DefaultAppProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EAEC8A62D05DB8D001AA50C /* DefaultAppProcessor.swift */; };
|
||||||
|
0EAEC8AA2D05DB8D001AA50C /* DefaultTunnelProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EAEC8A72D05DB8D001AA50C /* DefaultTunnelProcessor.swift */; };
|
||||||
0EB08B982CA46F4900A02591 /* AppPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0EB08B962CA46F4900A02591 /* AppPlist.strings */; };
|
0EB08B982CA46F4900A02591 /* AppPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0EB08B962CA46F4900A02591 /* AppPlist.strings */; };
|
||||||
0EBE80DC2BF55C0E00E36A20 /* TunnelLibrary in Frameworks */ = {isa = PBXBuildFile; productRef = 0EBE80DB2BF55C0E00E36A20 /* TunnelLibrary */; };
|
0EBE80DC2BF55C0E00E36A20 /* TunnelLibrary in Frameworks */ = {isa = PBXBuildFile; productRef = 0EBE80DB2BF55C0E00E36A20 /* TunnelLibrary */; };
|
||||||
0EC066D12C7DC47600D88A94 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0EC066D02C7DC47600D88A94 /* LaunchScreen.storyboard */; platformFilter = ios; };
|
0EC066D12C7DC47600D88A94 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0EC066D02C7DC47600D88A94 /* LaunchScreen.storyboard */; platformFilter = ios; };
|
||||||
|
@ -161,6 +163,8 @@
|
||||||
0E916B7B2CF811EB0072921A /* XCUIElement+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCUIElement+Extensions.swift"; sourceTree = "<group>"; };
|
0E916B7B2CF811EB0072921A /* XCUIElement+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCUIElement+Extensions.swift"; sourceTree = "<group>"; };
|
||||||
0E94EE5C2B93570600588243 /* Tunnel.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Tunnel.plist; sourceTree = "<group>"; };
|
0E94EE5C2B93570600588243 /* Tunnel.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Tunnel.plist; sourceTree = "<group>"; };
|
||||||
0EAD6A1A2CF7F79A00CC1F02 /* ScreenshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenshotTests.swift; sourceTree = "<group>"; };
|
0EAD6A1A2CF7F79A00CC1F02 /* ScreenshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenshotTests.swift; sourceTree = "<group>"; };
|
||||||
|
0EAEC8A62D05DB8D001AA50C /* DefaultAppProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultAppProcessor.swift; sourceTree = "<group>"; };
|
||||||
|
0EAEC8A72D05DB8D001AA50C /* DefaultTunnelProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultTunnelProcessor.swift; sourceTree = "<group>"; };
|
||||||
0EB08B972CA46F4900A02591 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/AppPlist.strings; sourceTree = "<group>"; };
|
0EB08B972CA46F4900A02591 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/AppPlist.strings; sourceTree = "<group>"; };
|
||||||
0EBE80DD2BF55C9100E36A20 /* Library */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Library; sourceTree = "<group>"; };
|
0EBE80DD2BF55C9100E36A20 /* Library */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Library; sourceTree = "<group>"; };
|
||||||
0EC066D02C7DC47600D88A94 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
|
0EC066D02C7DC47600D88A94 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
|
@ -341,6 +345,8 @@
|
||||||
children = (
|
children = (
|
||||||
0E6EEEE62CF8CB090076E2B0 /* Testing */,
|
0E6EEEE62CF8CB090076E2B0 /* Testing */,
|
||||||
0EC797402B9378E000C093B7 /* AppContext+Shared.swift */,
|
0EC797402B9378E000C093B7 /* AppContext+Shared.swift */,
|
||||||
|
0EAEC8A62D05DB8D001AA50C /* DefaultAppProcessor.swift */,
|
||||||
|
0EAEC8A72D05DB8D001AA50C /* DefaultTunnelProcessor.swift */,
|
||||||
0E8195592CFDA75200CC8FFD /* Dependencies.swift */,
|
0E8195592CFDA75200CC8FFD /* Dependencies.swift */,
|
||||||
0EC797412B9378E000C093B7 /* Shared.swift */,
|
0EC797412B9378E000C093B7 /* Shared.swift */,
|
||||||
0E483E822CE6501100584B32 /* Shared+App.swift */,
|
0E483E822CE6501100584B32 /* Shared+App.swift */,
|
||||||
|
@ -681,6 +687,7 @@
|
||||||
0E7C3CCD2C9AF44600B72E69 /* AppDelegate.swift in Sources */,
|
0E7C3CCD2C9AF44600B72E69 /* AppDelegate.swift in Sources */,
|
||||||
0ED61CFA2CD04192008FE259 /* App+iOS.swift in Sources */,
|
0ED61CFA2CD04192008FE259 /* App+iOS.swift in Sources */,
|
||||||
0E7E3D6B2B9345FD002BBDB4 /* PassepartoutApp.swift in Sources */,
|
0E7E3D6B2B9345FD002BBDB4 /* PassepartoutApp.swift in Sources */,
|
||||||
|
0EAEC8A92D05DB8D001AA50C /* DefaultAppProcessor.swift in Sources */,
|
||||||
0EC797422B9378E000C093B7 /* AppContext+Shared.swift in Sources */,
|
0EC797422B9378E000C093B7 /* AppContext+Shared.swift in Sources */,
|
||||||
0EE8D7E12CD112C200F6600C /* App+tvOS.swift in Sources */,
|
0EE8D7E12CD112C200F6600C /* App+tvOS.swift in Sources */,
|
||||||
0E81955A2CFDA75200CC8FFD /* Dependencies.swift in Sources */,
|
0E81955A2CFDA75200CC8FFD /* Dependencies.swift in Sources */,
|
||||||
|
@ -729,6 +736,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
0E81955B2CFDA7BF00CC8FFD /* Dependencies.swift in Sources */,
|
0E81955B2CFDA7BF00CC8FFD /* Dependencies.swift in Sources */,
|
||||||
|
0EAEC8AA2D05DB8D001AA50C /* DefaultTunnelProcessor.swift in Sources */,
|
||||||
0E94EE582B93554B00588243 /* PacketTunnelProvider.swift in Sources */,
|
0E94EE582B93554B00588243 /* PacketTunnelProvider.swift in Sources */,
|
||||||
0E483E812CE64D6B00584B32 /* Shared+Tunnel.swift in Sources */,
|
0E483E812CE64D6B00584B32 /* Shared+Tunnel.swift in Sources */,
|
||||||
0EC797442B93790600C093B7 /* Shared.swift in Sources */,
|
0EC797442B93790600C093B7 /* Shared.swift in Sources */,
|
||||||
|
|
|
@ -39,7 +39,7 @@ import UITesting
|
||||||
extension AppContext {
|
extension AppContext {
|
||||||
static let shared: AppContext = {
|
static let shared: AppContext = {
|
||||||
let iapManager: IAPManager = .sharedForApp
|
let iapManager: IAPManager = .sharedForApp
|
||||||
let processor = InAppProcessor.sharedImplementation(with: iapManager) {
|
let processor = DefaultAppProcessor(iapManager: iapManager) {
|
||||||
$0.localizedPreview
|
$0.localizedPreview
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
//
|
||||||
|
// DefaultAppProcessor.swift
|
||||||
|
// Passepartout
|
||||||
|
//
|
||||||
|
// Created by Davide De Rosa on 10/6/24.
|
||||||
|
// Copyright (c) 2024 Davide De Rosa. All rights reserved.
|
||||||
|
//
|
||||||
|
// https://github.com/passepartoutvpn
|
||||||
|
//
|
||||||
|
// This file is part of Passepartout.
|
||||||
|
//
|
||||||
|
// Passepartout 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.
|
||||||
|
//
|
||||||
|
// Passepartout 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 Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
import CommonLibrary
|
||||||
|
import Foundation
|
||||||
|
import PassepartoutKit
|
||||||
|
|
||||||
|
final class DefaultAppProcessor: Sendable {
|
||||||
|
private let iapManager: IAPManager
|
||||||
|
|
||||||
|
private let preview: @Sendable (Profile) -> ProfilePreview
|
||||||
|
|
||||||
|
init(iapManager: IAPManager, preview: @escaping @Sendable (Profile) -> ProfilePreview) {
|
||||||
|
self.iapManager = iapManager
|
||||||
|
self.preview = preview
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension DefaultAppProcessor: ProfileProcessor {
|
||||||
|
func isIncluded(_ profile: Profile) -> Bool {
|
||||||
|
Dependencies.ProfileManager.isIncluded(iapManager, profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
func preview(from profile: Profile) -> ProfilePreview {
|
||||||
|
preview(profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
func requiredFeatures(_ profile: Profile) -> Set<AppFeature>? {
|
||||||
|
do {
|
||||||
|
try iapManager.verify(profile)
|
||||||
|
return nil
|
||||||
|
} catch AppError.ineligibleProfile(let requiredFeatures) {
|
||||||
|
return requiredFeatures
|
||||||
|
} catch {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func willRebuild(_ builder: Profile.Builder) throws -> Profile.Builder {
|
||||||
|
builder
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension DefaultAppProcessor: AppTunnelProcessor {
|
||||||
|
func title(for profile: Profile) -> String {
|
||||||
|
Dependencies.ProfileManager.sharedTitle(profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
func willInstall(_ profile: Profile) throws -> Profile {
|
||||||
|
try iapManager.verify(profile)
|
||||||
|
|
||||||
|
// validate provider modules
|
||||||
|
do {
|
||||||
|
_ = try profile.withProviderModules()
|
||||||
|
return profile
|
||||||
|
} catch {
|
||||||
|
pp_log(.app, .error, "Unable to inject provider modules: \(error)")
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
//
|
//
|
||||||
// TunnelProcessor.swift
|
// DefaultTunnelProcessor.swift
|
||||||
// Passepartout
|
// Passepartout
|
||||||
//
|
//
|
||||||
// Created by Davide De Rosa on 11/20/24.
|
// Created by Davide De Rosa on 12/8/24.
|
||||||
// Copyright (c) 2024 Davide De Rosa. All rights reserved.
|
// Copyright (c) 2024 Davide De Rosa. All rights reserved.
|
||||||
//
|
//
|
||||||
// https://github.com/passepartoutvpn
|
// https://github.com/passepartoutvpn
|
||||||
|
@ -23,11 +23,20 @@
|
||||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import CommonLibrary
|
||||||
import Foundation
|
import Foundation
|
||||||
import PassepartoutKit
|
import PassepartoutKit
|
||||||
|
|
||||||
public protocol TunnelProcessor {
|
final class DefaultTunnelProcessor: Sendable {
|
||||||
func title(for profile: Profile) -> String
|
private let preferencesManager: PreferencesManager
|
||||||
|
|
||||||
func willInstall(_ profile: Profile) throws -> Profile
|
init(preferencesManager: PreferencesManager) {
|
||||||
|
self.preferencesManager = preferencesManager
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension DefaultTunnelProcessor: PacketTunnelProcessor {
|
||||||
|
func willStart(_ profile: Profile) throws -> Profile {
|
||||||
|
profile
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -89,51 +89,7 @@ extension TunnelEnvironment where Self == AppGroupEnvironment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension InAppProcessor {
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
static func sharedImplementation(with iapManager: IAPManager, preview: @escaping (Profile) -> ProfilePreview) -> InAppProcessor {
|
|
||||||
InAppProcessor(
|
|
||||||
iapManager: iapManager,
|
|
||||||
title: {
|
|
||||||
Dependencies.ProfileManager.sharedTitle($0)
|
|
||||||
},
|
|
||||||
isIncluded: {
|
|
||||||
Dependencies.ProfileManager.isIncluded($0, $1)
|
|
||||||
},
|
|
||||||
preview: preview,
|
|
||||||
requiredFeatures: { iap, profile in
|
|
||||||
do {
|
|
||||||
try iap.verify(profile)
|
|
||||||
return nil
|
|
||||||
} catch AppError.ineligibleProfile(let requiredFeatures) {
|
|
||||||
return requiredFeatures
|
|
||||||
} catch {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
},
|
|
||||||
willRebuild: { _, builder in
|
|
||||||
builder
|
|
||||||
},
|
|
||||||
willInstall: { iap, profile in
|
|
||||||
try iap.verify(profile)
|
|
||||||
|
|
||||||
// validate provider modules
|
|
||||||
do {
|
|
||||||
_ = try profile.withProviderModules()
|
|
||||||
return profile
|
|
||||||
} catch {
|
|
||||||
pp_log(.app, .error, "Unable to inject provider modules: \(error)")
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension PreferencesManager {
|
extension PreferencesManager {
|
||||||
|
|
||||||
@MainActor
|
|
||||||
static func sharedImplementation(withCloudKit: Bool) -> PreferencesManager {
|
static func sharedImplementation(withCloudKit: Bool) -> PreferencesManager {
|
||||||
let preferencesStore = CoreDataPersistentStore(
|
let preferencesStore = CoreDataPersistentStore(
|
||||||
logger: .default,
|
logger: .default,
|
||||||
|
|
|
@ -40,7 +40,7 @@ extension AppContext {
|
||||||
[]
|
[]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
let processor = InAppProcessor.sharedImplementation(with: iapManager) {
|
let processor = DefaultAppProcessor(iapManager: iapManager) {
|
||||||
$0.localizedPreview
|
$0.localizedPreview
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,12 +36,14 @@ final class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable {
|
||||||
parameters: Constants.shared.log,
|
parameters: Constants.shared.log,
|
||||||
logsPrivateData: UserDefaults.appGroup.bool(forKey: AppPreference.logsPrivateData.key)
|
logsPrivateData: UserDefaults.appGroup.bool(forKey: AppPreference.logsPrivateData.key)
|
||||||
)
|
)
|
||||||
|
let processor = DefaultTunnelProcessor(preferencesManager: .sharedForTunnel)
|
||||||
do {
|
do {
|
||||||
fwd = try await NEPTPForwarder(
|
fwd = try await NEPTPForwarder(
|
||||||
provider: self,
|
provider: self,
|
||||||
decoder: Registry.sharedProtocolCoder,
|
decoder: Registry.sharedProtocolCoder,
|
||||||
registry: .shared,
|
registry: .shared,
|
||||||
environment: .shared
|
environment: .shared,
|
||||||
|
profileBlock: processor.willStart
|
||||||
)
|
)
|
||||||
guard let fwd else {
|
guard let fwd else {
|
||||||
fatalError("NEPTPForwarder nil without throwing error?")
|
fatalError("NEPTPForwarder nil without throwing error?")
|
||||||
|
|
Loading…
Reference in New Issue