@@ -24,7 +24,6 @@ import BrowserServicesKit
24
24
import NetworkExtension
25
25
import NetworkProtection
26
26
import SystemExtensions
27
- import Common
28
27
29
28
enum NetworkProtectionConnectionStatus {
30
29
case notConfigured
@@ -75,11 +74,10 @@ final class DefaultNetworkProtectionProvider: NetworkProtectionProvider {
75
74
/// The logger that this object will use for errors that are handled by this class.
76
75
///
77
76
private let logger : NetworkProtectionLogger
78
-
79
- /// Handles registration of the current device with the Network Protection backend.
80
- /// The manager is also responsible to maintaining the current known list of backend servers, and allowing the user to pick which one they connect to.
81
- ///
82
- private let deviceManager : NetworkProtectionDeviceManagement
77
+
78
+ /// Stores the last controller error for the purpose of updating the UI as needed..
79
+ ///
80
+ private let controllerErrorStore = NetworkProtectionControllerErrorStore ( )
83
81
84
82
// MARK: - Notifications & Observers
85
83
@@ -92,12 +90,6 @@ final class DefaultNetworkProtectionProvider: NetworkProtectionProvider {
92
90
private var configChangeObserverToken : NSObjectProtocol ?
93
91
94
92
let configChangePublisher = CurrentValueSubject < Void , Never > ( ( ) )
95
-
96
- // MARK: - Bundle Identifiers
97
-
98
- var extensionBundleIdentifier : String {
99
- NetworkProtectionBundle . extensionBundle ( ) . bundleIdentifier!
100
- }
101
93
102
94
// MARK: - VPN Tunnel & Configuration
103
95
@@ -192,11 +184,8 @@ final class DefaultNetworkProtectionProvider: NetworkProtectionProvider {
192
184
193
185
convenience init ( ) {
194
186
let keychainStore = NetworkProtectionKeychainStore ( useSystemKeychain: NetworkProtectionBundle . usesSystemKeychain ( ) )
195
- let deviceManager = NetworkProtectionDeviceManager ( keyStore: keychainStore,
196
- errorEvents: Self . networkProtectionDebugEvents)
197
187
198
188
self . init ( notificationCenter: . default,
199
- deviceManager: deviceManager,
200
189
logger: DefaultNetworkProtectionLogger ( ) )
201
190
}
202
191
@@ -207,11 +196,9 @@ final class DefaultNetworkProtectionProvider: NetworkProtectionProvider {
207
196
/// - logger: (meant for testing) the logger that this object will use.
208
197
///
209
198
init ( notificationCenter: NotificationCenter ,
210
- deviceManager: NetworkProtectionDeviceManagement ,
211
199
logger: NetworkProtectionLogger ) {
212
200
213
201
self . logger = logger
214
- self . deviceManager = deviceManager
215
202
self . notificationCenter = notificationCenter
216
203
217
204
startObservingNotifications ( )
@@ -261,65 +248,6 @@ final class DefaultNetworkProtectionProvider: NetworkProtectionProvider {
261
248
configChangeObserverToken = nil
262
249
}
263
250
264
- // MARK: - Error Reporting
265
-
266
- static let networkProtectionDebugEvents : EventMapping < NetworkProtectionError > ? = . init { event, _, _, _ in
267
- let domainEvent : Pixel . Event
268
-
269
- switch event {
270
- case . noServerRegistrationInfo:
271
- domainEvent = . networkProtectionTunnelConfigurationNoServerRegistrationInfo
272
- case . couldNotSelectClosestServer:
273
- domainEvent = . networkProtectionTunnelConfigurationCouldNotSelectClosestServer
274
- case . couldNotGetPeerPublicKey:
275
- domainEvent = . networkProtectionTunnelConfigurationCouldNotGetPeerPublicKey
276
- case . couldNotGetPeerHostName:
277
- domainEvent = . networkProtectionTunnelConfigurationCouldNotGetPeerHostName
278
- case . couldNotGetInterfaceAddressRange:
279
- domainEvent = . networkProtectionTunnelConfigurationCouldNotGetInterfaceAddressRange
280
-
281
- case . failedToFetchServerList:
282
- return
283
- case . failedToParseServerListResponse:
284
- domainEvent = . networkProtectionClientFailedToParseServerListResponse
285
- case . failedToEncodeRegisterKeyRequest:
286
- domainEvent = . networkProtectionClientFailedToEncodeRegisterKeyRequest
287
- case . failedToFetchRegisteredServers:
288
- return
289
- case . failedToParseRegisteredServersResponse:
290
- domainEvent = . networkProtectionClientFailedToParseRegisteredServersResponse
291
- case . serverListInconsistency:
292
- // - TODO: not sure what to do here
293
- return
294
-
295
- case . failedToEncodeServerList:
296
- domainEvent = . networkProtectionServerListStoreFailedToEncodeServerList
297
- case . failedToWriteServerList( let eventError) :
298
- domainEvent = . networkProtectionServerListStoreFailedToWriteServerList( error: eventError)
299
- case . noServerListFound:
300
- return
301
- case . couldNotCreateServerListDirectory:
302
- return
303
-
304
- case . failedToReadServerList( let eventError) :
305
- domainEvent = . networkProtectionServerListStoreFailedToReadServerList( error: eventError)
306
-
307
- case . failedToCastKeychainValueToData( let field) :
308
- domainEvent = . networkProtectionKeychainErrorFailedToCastKeychainValueToData( field: field)
309
- case . keychainReadError( let field, let status) :
310
- domainEvent = . networkProtectionKeychainReadError( field: field, status: status)
311
- case . keychainWriteError( let field, let status) :
312
- domainEvent = . networkProtectionKeychainWriteError( field: field, status: status)
313
- case . keychainDeleteError( let field, let status) :
314
- domainEvent = . networkProtectionKeychainDeleteError( field: field, status: status)
315
-
316
- case . unhandledError( function: let function, line: let line, error: let error) :
317
- domainEvent = . networkProtectionUnhandledError( function: function, line: line, error: error)
318
- }
319
-
320
- Pixel . fire ( domainEvent, includeAppVersionParameter: true )
321
- }
322
-
323
251
// MARK: - Notifications: Handling
324
252
325
253
static let statusChangeQueue : OperationQueue = {
@@ -371,9 +299,6 @@ final class DefaultNetworkProtectionProvider: NetworkProtectionProvider {
371
299
/// Setups the tunnel manager if it's not set up already.
372
300
///
373
301
private func setup( _ tunnelManager: NETunnelProviderManager ) async throws {
374
- // 1 - If configuration exists... let it through (but what if it's broken? the service will take care of it)
375
- // 2 - If a configuration doesn't exist, fill in a dummy one (can this cause issues?)
376
-
377
302
if tunnelManager. localizedDescription == nil {
378
303
tunnelManager. localizedDescription = UserText . networkProtectionTunnelName
379
304
}
@@ -382,12 +307,9 @@ final class DefaultNetworkProtectionProvider: NetworkProtectionProvider {
382
307
tunnelManager. isEnabled = true
383
308
}
384
309
385
- guard tunnelManager. protocolConfiguration == nil else {
386
- return
387
- }
388
-
389
310
let protocolConfiguration = NETunnelProviderProtocol ( )
390
311
protocolConfiguration. serverAddress = " 127.0.0.1 " // Dummy address... the NetP service will take care of grabbing a real server
312
+ protocolConfiguration. providerBundleIdentifier = NetworkProtectionBundle . extensionBundle ( ) . bundleIdentifier
391
313
tunnelManager. protocolConfiguration = protocolConfiguration
392
314
}
393
315
@@ -409,30 +331,65 @@ final class DefaultNetworkProtectionProvider: NetworkProtectionProvider {
409
331
return false
410
332
}
411
333
}
334
+
335
+ // MARK: - Ensure things are working
336
+
337
+ /// - Returns: `true` if the system extension and the background agent were activated successfully
338
+ ///
339
+ private func ensureSystemExtensionAndAgentAreActivated( ) async throws -> Bool {
340
+ NetworkProtectionAgentManager . current. enable ( )
341
+
342
+ #if NETP_SYSTEM_EXTENSION
343
+ if case . willActivateAfterReboot = try await SystemExtensionManager . shared. activate ( waitingForUserApprovalHandler: { [ weak self] in
344
+ self ? . controllerErrorStore. lastErrorMessage = " Go to Security & Privacy in System Settings to allow Network Protection to activate "
345
+ } ) {
346
+ controllerErrorStore. lastErrorMessage = " Please reboot to activate Network Protection "
347
+ return false
348
+ }
349
+ #endif
350
+
351
+ return true
352
+ }
412
353
413
354
// MARK: - Starting & Stopping the VPN
414
355
415
356
/// Starts the VPN connection used for Network Protection
416
357
///
417
358
func start( ) async throws {
418
- NetworkProtectionAgentManager . current. enable ( )
419
- let tunnelManager = try await loadOrMakeTunnelManager ( )
359
+ guard try await ensureSystemExtensionAndAgentAreActivated ( ) else {
360
+ return
361
+ }
362
+
363
+ controllerErrorStore. lastErrorMessage = nil
364
+ let tunnelManager : NETunnelProviderManager
365
+
366
+ do {
367
+ tunnelManager = try await loadOrMakeTunnelManager ( )
368
+ } catch {
369
+ controllerErrorStore. lastErrorMessage = error. localizedDescription
370
+ throw error
371
+ }
420
372
421
373
switch tunnelManager. connection. status {
422
374
case . invalid:
423
375
reloadTunnelManager ( )
424
376
try await start ( )
425
- case . disconnected, . disconnecting:
377
+ case . connected:
378
+ // Intentional no-op
379
+ break
380
+ default :
426
381
var options = [ String: NSObject] ( )
427
-
382
+
428
383
if let selectedServerName = NetworkProtectionSelectedServerUserDefaultsStore ( ) . selectedServer. stringValue {
429
384
options [ " selectedServer " ] = selectedServerName as NSString
430
385
}
431
-
432
- try tunnelManager. connection. startVPNTunnel ( options: options)
433
- default :
434
- // Intentional no-op
435
- break
386
+
387
+ do {
388
+ try tunnelManager. connection. startVPNTunnel ( options: options)
389
+ } catch {
390
+ controllerErrorStore. lastErrorMessage = error. localizedDescription
391
+ throw error
392
+ }
436
393
}
437
394
}
438
395
0 commit comments