handle app context changes

This commit is contained in:
Adam Velebil 2024-09-05 15:09:51 +02:00
parent 516d776921
commit 4e1abf2b3b
No known key found for this signature in database
GPG Key ID: C9B1E4A3CBBD2E10
4 changed files with 24 additions and 5 deletions

View File

@ -357,6 +357,7 @@ class MainActivity : FlutterFragmentActivity() {
deviceManager.setDeviceInfo(deviceInfo, scpKeyParams)
val supportedContexts = DeviceManager.getSupportedContexts(deviceInfo)
logger.debug("Connected key supports: {}", supportedContexts)
var switchedContext: Boolean = false
if (!supportedContexts.contains(viewModel.appContext.value)) {
val preferredContext = DeviceManager.getPreferredContext(supportedContexts)
logger.debug(
@ -364,17 +365,17 @@ class MainActivity : FlutterFragmentActivity() {
viewModel.appContext.value,
preferredContext
)
switchContext(preferredContext)
switchedContext = switchContext(preferredContext)
}
if (contextManager == null && supportedContexts.isNotEmpty()) {
switchContext(DeviceManager.getPreferredContext(supportedContexts))
switchedContext = switchContext(DeviceManager.getPreferredContext(supportedContexts))
}
contextManager?.let {
try {
it.processYubiKey(device)
if (device is NfcYubiKeyDevice) {
if (!switchedContext && device is NfcYubiKeyDevice) {
appMethodChannel.nfcActivityStateChanged(NfcActivityState.PROCESSING_FINISHED)
device.remove {
appMethodChannel.nfcActivityStateChanged(NfcActivityState.READY)
@ -440,7 +441,8 @@ class MainActivity : FlutterFragmentActivity() {
}
}
private fun switchContext(appContext: OperationContext) {
private fun switchContext(appContext: OperationContext) : Boolean {
var switchHappened = false
// TODO: refactor this when more OperationContext are handled
// only recreate the contextManager object if it cannot be reused
if (appContext == OperationContext.Home ||
@ -454,6 +456,7 @@ class MainActivity : FlutterFragmentActivity() {
} else {
contextManager?.dispose()
contextManager = null
switchHappened = true
}
if (contextManager == null) {
@ -481,6 +484,7 @@ class MainActivity : FlutterFragmentActivity() {
else -> null
}
}
return switchHappened
}
override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine) {

View File

@ -20,6 +20,7 @@ import androidx.collection.ArraySet
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.Observer
import com.yubico.authenticator.ContextDisposedException
import com.yubico.authenticator.DialogManager
import com.yubico.authenticator.MainActivity
import com.yubico.authenticator.MainViewModel
@ -214,10 +215,17 @@ class DeviceManager(
} catch (e: Exception) {
logger.debug("NFC action failed, asking to try again. Failure: ", e)
if (e is CancellationException) {
throw e
}
if (e is ContextDisposedException) {
// the key does not have the needed context anymore
// we cannot continue
appMethodChannel.nfcActivityStateChanged(NfcActivityState.PROCESSING_INTERRUPTED)
throw e
}
appMethodChannel.nfcActivityStateChanged(NfcActivityState.PROCESSING_INTERRUPTED)
}

View File

@ -216,6 +216,7 @@ class OathManager(
oathViewModel.clearSession()
oathViewModel.updateCredentials(mapOf())
pendingAction?.invoke(Result.failure(ContextDisposedException()))
pendingAction = null
coroutineScope.cancel()
}

View File

@ -24,11 +24,17 @@ extension Decoder on PlatformException {
bool _isApduException() => code == 'ApduException';
bool _isContextDisposed() => code == 'ContextDisposedException';
Exception decode() {
if (_isCancellation()) {
return CancellationException();
}
if (_isContextDisposed()) {
return CancellationException();
}
if (message != null && _isApduException()) {
final regExp = RegExp(
r'^com.yubico.yubikit.core.smartcard.ApduException: APDU error: 0x(.*)$');