Skip to content

Commit

Permalink
NetP test & interruption notifications (#2047)
Browse files Browse the repository at this point in the history
Co-authored-by: Diego Rey Mendez <[email protected]>
  • Loading branch information
graeme and diegoreymendez authored Sep 28, 2023
1 parent ef619c6 commit e60ac12
Show file tree
Hide file tree
Showing 8 changed files with 272 additions and 64 deletions.
20 changes: 18 additions & 2 deletions DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,7 @@
EE0153ED2A6FF9E6002A8B26 /* NetworkProtectionRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE0153EC2A6FF9E6002A8B26 /* NetworkProtectionRootView.swift */; };
EE0153EF2A70021E002A8B26 /* NetworkProtectionInviteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE0153EE2A70021E002A8B26 /* NetworkProtectionInviteView.swift */; };
EE276BEA2A77F823009167B6 /* NetworkProtectionRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE276BE92A77F823009167B6 /* NetworkProtectionRootViewController.swift */; };
EE3766DE2AC5945500AAB575 /* NetworkProtectionUNNotificationPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE3766DD2AC5945500AAB575 /* NetworkProtectionUNNotificationPresenter.swift */; };
EE3B226B29DE0F110082298A /* MockInternalUserStoring.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE3B226A29DE0F110082298A /* MockInternalUserStoring.swift */; };
EE3B226C29DE0FD30082298A /* MockInternalUserStoring.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE3B226A29DE0F110082298A /* MockInternalUserStoring.swift */; };
EE41BD192A729E9C00546C57 /* NetworkProtectionInviteViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE41BD182A729E9C00546C57 /* NetworkProtectionInviteViewModelTests.swift */; };
Expand All @@ -763,6 +764,7 @@
EEEB80A32A421CE600386378 /* NetworkProtectionPacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEB80A22A421CE600386378 /* NetworkProtectionPacketTunnelProvider.swift */; };
EEF0F8CC2ABC832300630031 /* NetworkProtectionDebugFeatures.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEF0F8CB2ABC832200630031 /* NetworkProtectionDebugFeatures.swift */; };
EEFAB4672A73C230008A38E4 /* NetworkProtectionTestUtils in Frameworks */ = {isa = PBXBuildFile; productRef = EEFAB4662A73C230008A38E4 /* NetworkProtectionTestUtils */; };
EEFC6A602AC0F2F80065027D /* UserText.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEFC6A5F2AC0F2F80065027D /* UserText.swift */; };
EEFD562F2A65B6CA00DAEC48 /* NetworkProtectionInviteViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEFD562E2A65B6CA00DAEC48 /* NetworkProtectionInviteViewModel.swift */; };
EEFE9C732A603CE9005B0A26 /* NetworkProtectionStatusViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEFE9C722A603CE9005B0A26 /* NetworkProtectionStatusViewModelTests.swift */; };
F103073B1E7C91330059FEC7 /* BookmarksDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = F103073A1E7C91330059FEC7 /* BookmarksDataSource.swift */; };
Expand Down Expand Up @@ -2332,6 +2334,7 @@
EE0153EC2A6FF9E6002A8B26 /* NetworkProtectionRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionRootView.swift; sourceTree = "<group>"; };
EE0153EE2A70021E002A8B26 /* NetworkProtectionInviteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionInviteView.swift; sourceTree = "<group>"; };
EE276BE92A77F823009167B6 /* NetworkProtectionRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionRootViewController.swift; sourceTree = "<group>"; };
EE3766DD2AC5945500AAB575 /* NetworkProtectionUNNotificationPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionUNNotificationPresenter.swift; sourceTree = "<group>"; };
EE3B226A29DE0F110082298A /* MockInternalUserStoring.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockInternalUserStoring.swift; sourceTree = "<group>"; };
EE3B98EA2A9634CC002F63A0 /* DuckDuckGoAlpha.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DuckDuckGoAlpha.entitlements; sourceTree = "<group>"; };
EE3B98EB2A963515002F63A0 /* WidgetsExtensionAlpha.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WidgetsExtensionAlpha.entitlements; sourceTree = "<group>"; };
Expand All @@ -2350,6 +2353,7 @@
EEB8FDB92A990AEE00EBEDCF /* Configuration-Alpha.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Configuration-Alpha.xcconfig"; path = "Configuration/Configuration-Alpha.xcconfig"; sourceTree = "<group>"; };
EEEB80A22A421CE600386378 /* NetworkProtectionPacketTunnelProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionPacketTunnelProvider.swift; sourceTree = "<group>"; };
EEF0F8CB2ABC832200630031 /* NetworkProtectionDebugFeatures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkProtectionDebugFeatures.swift; sourceTree = "<group>"; };
EEFC6A5F2AC0F2F80065027D /* UserText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserText.swift; sourceTree = "<group>"; };
EEFD562E2A65B6CA00DAEC48 /* NetworkProtectionInviteViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionInviteViewModel.swift; sourceTree = "<group>"; };
EEFE9C722A603CE9005B0A26 /* NetworkProtectionStatusViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionStatusViewModelTests.swift; sourceTree = "<group>"; };
F103073A1E7C91330059FEC7 /* BookmarksDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarksDataSource.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2604,13 +2608,14 @@
02025665298818B200E694E7 /* PacketTunnelProvider */ = {
isa = PBXGroup;
children = (
EE3766DC2AC5940A00AAB575 /* NetworkProtection */,
EE3B98EC2A963538002F63A0 /* PacketTunnelProviderAlpha.entitlements */,
02025670298818CB00E694E7 /* ProxyServer */,
02025666298818B200E694E7 /* AppTrackingProtectionPacketTunnelProvider.swift */,
02025B1429884EA500E694E7 /* DDGObserverFactory.swift */,
02025668298818B200E694E7 /* Info.plist */,
02025669298818B200E694E7 /* PacketTunnelProvider.entitlements */,
EEEB80A22A421CE600386378 /* NetworkProtectionPacketTunnelProvider.swift */,
EEFC6A5F2AC0F2F80065027D /* UserText.swift */,
);
path = PacketTunnelProvider;
sourceTree = "<group>";
Expand Down Expand Up @@ -4344,6 +4349,15 @@
name = Root;
sourceTree = "<group>";
};
EE3766DC2AC5940A00AAB575 /* NetworkProtection */ = {
isa = PBXGroup;
children = (
EEEB80A22A421CE600386378 /* NetworkProtectionPacketTunnelProvider.swift */,
EE3766DD2AC5945500AAB575 /* NetworkProtectionUNNotificationPresenter.swift */,
);
path = NetworkProtection;
sourceTree = "<group>";
};
EE3B226929DE0EE10082298A /* FeatureFlags */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -5962,6 +5976,7 @@
4BEF656D2989C2FC00B650CB /* EventType.swift in Sources */,
02025AAC2988229800E694E7 /* GCDHTTPProxyServer.swift in Sources */,
02025AAD2988229800E694E7 /* NWUDPSocket.swift in Sources */,
EE3766DE2AC5945500AAB575 /* NetworkProtectionUNNotificationPresenter.swift in Sources */,
02025AAE2988229800E694E7 /* RawTCPSocketProtocol.swift in Sources */,
02025AAF2988229800E694E7 /* NWTCPSocket.swift in Sources */,
02025AB12988229800E694E7 /* RawSocketFactory.swift in Sources */,
Expand Down Expand Up @@ -6005,6 +6020,7 @@
02025AEB2988229800E694E7 /* Utils.swift in Sources */,
02025AEC2988229800E694E7 /* AppTrackingProtectionPacketTunnelProvider.swift in Sources */,
02025B1029884DC500E694E7 /* AppTrackerDataParser.swift in Sources */,
EEFC6A602AC0F2F80065027D /* UserText.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -8928,7 +8944,7 @@
repositoryURL = "https://github.com/DuckDuckGo/BrowserServicesKit";
requirement = {
kind = exactVersion;
version = 80.2.1;
version = 80.3.0;
};
};
C14882EB27F211A000D59F0C /* XCRemoteSwiftPackageReference "SwiftSoup" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
"repositoryURL": "https://github.com/DuckDuckGo/BrowserServicesKit",
"state": {
"branch": null,
"revision": "e955f958201a91ef353c55236361e095357e9505",
"version": "80.2.1"
"revision": "2bed3ed259ca7bde33f3d41424345acfeff8031d",
"version": "80.3.0"
}
},
{
Expand Down
40 changes: 40 additions & 0 deletions DuckDuckGo/NetworkProtectionDebugUtilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,46 @@ final class NetworkProtectionDebugUtilities {

try? activeSession.sendProviderMessage(.expireRegistrationKey)
}

// MARK: - Notifications

func sendTestNotificationRequest() async throws {
guard let activeSession = try? await ConnectionSessionUtilities.activeSession() else {
return
}

try? activeSession.sendProviderMessage(.triggerTestNotification)
}

// MARK: - Failure Simulation

func triggerSimulation(_ option: NetworkProtectionSimulationOption) async {
guard let activeSession = try? await ConnectionSessionUtilities.activeSession() else {
return
}

guard let message = option.extensionMessage else {
return
}
try? activeSession.sendProviderMessage(message)
}
}

private extension NetworkProtectionSimulationOption {
var extensionMessage: ExtensionMessage? {
switch self {
case .crashFatalError:
return .simulateTunnelFatalError
case .crashMemory:
return .simulateTunnelMemoryOveruse
case .tunnelFailure:
return .simulateTunnelFailure
case .controllerFailure:
return nil
case .connectionInterruption:
return .simulateConnectionInterruption
}
}
}

#endif
73 changes: 56 additions & 17 deletions DuckDuckGo/NetworkProtectionDebugViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ final class NetworkProtectionDebugViewController: UITableViewController {
Sections.keychain: "Keychain",
Sections.debugFeature: "Debug Features",
Sections.simulateFailure: "Simulate Failure",
Sections.registrationKey: "Registration Key"
Sections.registrationKey: "Registration Key",
Sections.notifications: "Notifications"

]

Expand All @@ -44,6 +45,7 @@ final class NetworkProtectionDebugViewController: UITableViewController {
case debugFeature
case simulateFailure
case registrationKey
case notifications

}

Expand All @@ -63,7 +65,7 @@ final class NetworkProtectionDebugViewController: UITableViewController {
case controllerFailure
case crashFatalError
case crashMemory

case connectionInterruption
}

enum RegistrationKeyRows: Int, CaseIterable {
Expand All @@ -72,6 +74,12 @@ final class NetworkProtectionDebugViewController: UITableViewController {

}

enum NotificationsRows: Int, CaseIterable {

case triggerTestNotification

}

private let debugFeatures: NetworkProtectionDebugFeatures
private let tokenStore: NetworkProtectionTokenStore

Expand Down Expand Up @@ -122,6 +130,9 @@ final class NetworkProtectionDebugViewController: UITableViewController {
case .registrationKey:
configure(cell, forRegistrationKeyRow: indexPath.row)

case .notifications:
configure(cell, forNotificationRow: indexPath.row)

case.none:
break
}
Expand All @@ -135,6 +146,7 @@ final class NetworkProtectionDebugViewController: UITableViewController {
case .debugFeature: return DebugFeatureRows.allCases.count
case .simulateFailure: return SimulateFailureRows.allCases.count
case .registrationKey: return RegistrationKeyRows.allCases.count
case .notifications: return NotificationsRows.allCases.count
case .none: return 0

}
Expand All @@ -153,6 +165,8 @@ final class NetworkProtectionDebugViewController: UITableViewController {
didSelectSimulateFailure(at: indexPath)
case .registrationKey:
didSelectRegistationKeyAction(at: indexPath)
case .notifications:
didSelectTestNotificationAction(at: indexPath)
case .none:
break
}
Expand All @@ -172,18 +186,33 @@ final class NetworkProtectionDebugViewController: UITableViewController {
cell.textLabel?.text = "Tunnel: Crash (Fatal Error)"
case .crashMemory:
cell.textLabel?.text = "Tunnel: Crash (CPU/Memory)"
case .connectionInterruption:
cell.textLabel?.text = "Connection Interruption"
case .none:
break
}
}

private func didSelectSimulateFailure(at indexPath: IndexPath) {
switch SimulateFailureRows(rawValue: indexPath.row) {
case .controllerFailure: simulateFailure(option: .controllerFailure)
case .tunnelFailure: simulateFailure(option: .tunnelFailure)
case .crashFatalError: simulateFailure(option: .crashFatalError)
case .crashMemory: simulateFailure(option: .crashMemory)
case .none: return
case .controllerFailure:
NetworkProtectionTunnelController.shouldSimulateFailure = true
case .tunnelFailure:
triggerSimulation(.tunnelFailure)
case .crashFatalError:
triggerSimulation(.crashFatalError)
case .crashMemory:
triggerSimulation(.crashMemory)
case .connectionInterruption:
triggerSimulation(.connectionInterruption)
case .none:
break
}
}

private func triggerSimulation(_ option: NetworkProtectionSimulationOption) {
Task {
await NetworkProtectionDebugUtilities().triggerSimulation(option)
}
}

Expand Down Expand Up @@ -236,22 +265,32 @@ final class NetworkProtectionDebugViewController: UITableViewController {
}
}

// MARK: Selection Actions
// MARK: Notifications

private func clearAuthToken() {
try? tokenStore.deleteToken()
private func configure(_ cell: UITableViewCell, forNotificationRow row: Int) {
switch NotificationsRows(rawValue: row) {
case .triggerTestNotification:
cell.textLabel?.text = "Test Notification"
case .none:
break
}
}

private func simulateControllerFailure() {
NetworkProtectionTunnelController.enabledSimulationOption = .controllerFailure
private func didSelectTestNotificationAction(at indexPath: IndexPath) {
switch NotificationsRows(rawValue: indexPath.row) {
case .triggerTestNotification:
Task {
try await NetworkProtectionDebugUtilities().sendTestNotificationRequest()
}
case .none:
break
}
}

private func simulaterTunnelFailure() {
NetworkProtectionTunnelController.enabledSimulationOption = .crashFatalError
}
// MARK: Selection Actions

private func simulateFailure(option: NetworkProtectionSimulationOption) {
NetworkProtectionTunnelController.enabledSimulationOption = .crashMemory
private func clearAuthToken() {
try? tokenStore.deleteToken()
}
}

Expand Down
27 changes: 3 additions & 24 deletions DuckDuckGo/NetworkProtectionTunnelController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ import NetworkExtension
import NetworkProtection

final class NetworkProtectionTunnelController: TunnelController {
static var simulationOptions = NetworkProtectionSimulationOptions()
static var enabledSimulationOption: NetworkProtectionSimulationOption?
static var shouldSimulateFailure: Bool = false

private let debugFeatures = NetworkProtectionDebugFeatures()
private let tokenStore = NetworkProtectionKeychainTokenStore()
Expand Down Expand Up @@ -98,19 +97,14 @@ final class NetworkProtectionTunnelController: TunnelController {
private func start(_ tunnelManager: NETunnelProviderManager) throws {
var options = [String: NSObject]()

if Self.simulationOptions.isEnabled(.controllerFailure) {
Self.simulationOptions.setEnabled(false, option: .controllerFailure)
if Self.shouldSimulateFailure {
Self.shouldSimulateFailure = false
throw StartError.simulateControllerFailureError
}

options["activationAttemptId"] = UUID().uuidString as NSString
options["authToken"] = try tokenStore.fetchToken() as NSString?

if let optionKey = Self.enabledSimulationOption?.optionKey {
options[optionKey] = NSNumber(value: true)
Self.enabledSimulationOption = nil
}

do {
try tunnelManager.connection.startVPNTunnel(options: options)
} catch {
Expand Down Expand Up @@ -227,19 +221,4 @@ final class NetworkProtectionTunnelController: TunnelController {
}
}

private extension NetworkProtectionSimulationOption {
var optionKey: String? {
switch self {
case .crashFatalError:
return NetworkProtectionOptionKey.tunnelFatalErrorCrashSimulation
case .crashMemory:
return NetworkProtectionOptionKey.tunnelMemoryCrashSimulation
case .tunnelFailure:
return NetworkProtectionOptionKey.tunnelFailureSimulation
default:
return nil
}
}
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,9 @@ final class NetworkProtectionPacketTunnelProvider: PacketTunnelProvider {
let tokenStore = NetworkProtectionKeychainTokenStore(keychainType: .dataProtection(.unspecified),
errorEvents: nil)
let errorStore = NetworkProtectionTunnelErrorStore()
super.init(notificationsPresenter: DefaultNotificationPresenter(),
let notificationsPresenter = NetworkProtectionUNNotificationPresenter()
notificationsPresenter.requestAuthorization()
super.init(notificationsPresenter: notificationsPresenter,
tunnelHealthStore: NetworkProtectionTunnelHealthStore(),
controllerErrorStore: errorStore,
keychainType: .dataProtection(.unspecified),
Expand Down Expand Up @@ -201,21 +203,3 @@ final class NetworkProtectionPacketTunnelProvider: PacketTunnelProvider {
}
}
}

final class DefaultNotificationPresenter: NetworkProtectionNotificationsPresenter {

func showTestNotification() {
}

func showReconnectedNotification() {
}

func showReconnectingNotification() {
}

func showConnectionFailureNotification() {
}

func showSupersededNotification() {
}
}
Loading

0 comments on commit e60ac12

Please sign in to comment.