Regarding:
Case 1: NE was activated but chosen DontAllow option from the popup as shown below. As part of bootstrap, we are trying to save the preferences for the popup if filtermanger object is available & Not Allowed. But the Allow/Don'tAllow popup is not coming and configuring with Allow automatically.
I'm don't think I am understanding what your workflow is here. You are not trying to automatically activate the Network Configuration if the user has disallowed the prompt are you?
No, I want to keep the NE state as previous like 'Dont'Allow'. But NE is allowing without any user action after rebooting the machine. This is not expected behaviour.
Here, we want to confirm from the user to Allow/DontAllow the NE after machine reboot. So, we were added functionality like NEFilterManager.shared().saveToPreferences
for the popup to decide if user did not allow the NE for filtering previously. But this is not giving popup and allowing by default. Here NEFilterManager.shared().saveToPreferences
is calling before user login into the machine.
One more point, If we call NEFilterManager.shared().saveToPreferences
after user login into the machine then popup is coming to Allow/DontAllow. But, If I call this before user login into the machine then popup is not coming & NE is allowing by default.
Is this expected behaviour?
Below is the sample code to start the NE and startFilter()
is API to activate & Allow the NE.
class Controller: NSObject {
@objc func startFilter() -> NSNumber {
current_cmd = .start
if NEFilterManager.shared().isEnabled {
exit(Controller.ReturnCodes.success.rawValue)
}
if NEFilterManager.shared().providerConfiguration != nil {
NEFilterManager.shared().isEnabled = true
NEFilterManager.shared().saveToPreferences { serror in
DispatchQueue.main.async {
if let error = serror {
os_log("Error is saving NE configuration %@", error.localizedDescription)
exit(Controller.ReturnCodes.saveConfFailed.rawValue)
}
exit(Controller.ReturnCodes.success.rawValue)
}
}
}
else {
guard let extensionIdentifier = extensionBundle.bundleIdentifier else {
os_log("failed to get the bundleidentified before activation request")
return NSNumber(value:Controller.ReturnCodes.invalidBundleIdentifier.rawValue)
}
let activationRequest = OSSystemExtensionRequest.activationRequest(forExtensionWithIdentifier: extensionIdentifier, queue: .main)
activationRequest.delegate = self
OSSystemExtensionManager.shared.submitRequest(activationRequest)
}
return NSNumber(value: Controller.ReturnCodes.procStillRunning.rawValue)
}
// MARK: Content Filter Configuration Management
func enableFilterConfiguration() {
let filterManager = NEFilterManager.shared()
if filterManager.providerConfiguration == nil {
let providerConfiguration = NEFilterProviderConfiguration()
providerConfiguration.filterSockets = true
providerConfiguration.filterPackets = false
//providerConfiguration.filterBrowsers = false
filterManager.providerConfiguration = providerConfiguration
if let appName = Bundle.main.infoDictionary?["CFBundleName"] as? String {
filterManager.localizedDescription = appName
}
}
filterManager.isEnabled = true
filterManager.saveToPreferences { saveError in
DispatchQueue.main.async {
if let error = saveError {
os_log("Failed to save the filter configuration: %@", error.localizedDescription)
exit(Controller.ReturnCodes.saveConfFailed.rawValue)
}
exit(Controller.ReturnCodes.success.rawValue)
}
}
}
}
extension Controller: OSSystemExtensionRequestDelegate {
// MARK: OSSystemExtensionActivationRequestDelegate
func request(_ request: OSSystemExtensionRequest,didFinishWithResult result: OSSystemExtensionRequest.Result){
guard result == .completed else {
os_log("Unexpected result %d for system extension request", result.rawValue)
//status = .stopped
exit(Controller.ReturnCodes.RequestFailed.rawValue)
}
if self.current_cmd != .uninstall {
enableFilterConfiguration()
}
else {
exit(Controller.ReturnCodes.success.rawValue)
}
}
func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error) {
os_log("System extension request failed: %@", error.localizedDescription)
//status = .stopped
exit(Controller.ReturnCodes.RequestFailed.rawValue)
}
func requestNeedsUserApproval(_ request: OSSystemExtensionRequest) {
os_log("Extension %@ requires user approval", request.identifier)
}
func request(_ request: OSSystemExtensionRequest,
actionForReplacingExtension existing: OSSystemExtensionProperties,
withExtension extension: OSSystemExtensionProperties) -> OSSystemExtensionRequest.ReplacementAction {
os_log("Replacing extension %@ version %@ with version %@", request.identifier, existing.bundleShortVersion, `extension`.bundleShortVersion)
return .replace
}
}