mirror of
https://github.com/bitwarden/android.git
synced 2025-12-10 09:56:45 -06:00
[PM-24411] Extract pending intent management for Credential Manager requests (#5636)
This commit is contained in:
parent
38b92133ff
commit
f4c4e06dcc
@ -12,19 +12,16 @@ import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.vault.CipherListView
|
||||
import com.x8bit.bitwarden.data.autofill.util.login
|
||||
import com.x8bit.bitwarden.data.credentials.processor.GET_PASSKEY_INTENT
|
||||
import com.x8bit.bitwarden.data.credentials.processor.GET_PASSWORD_INTENT
|
||||
import com.x8bit.bitwarden.data.credentials.manager.CredentialManagerPendingIntentManager
|
||||
import com.x8bit.bitwarden.data.credentials.util.setBiometricPromptDataIfSupported
|
||||
import com.x8bit.bitwarden.data.platform.manager.BiometricsEncryptionManager
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
* Primary implementation of [CredentialEntryBuilder].
|
||||
*/
|
||||
class CredentialEntryBuilderImpl(
|
||||
private val context: Context,
|
||||
private val intentManager: IntentManager,
|
||||
private val pendingIntentManager: CredentialManagerPendingIntentManager,
|
||||
private val biometricsEncryptionManager: BiometricsEncryptionManager,
|
||||
) : CredentialEntryBuilder {
|
||||
|
||||
@ -69,15 +66,12 @@ class CredentialEntryBuilderImpl(
|
||||
context = context,
|
||||
username = fido2AutofillView.userNameForUi
|
||||
?: context.getString(BitwardenString.no_username),
|
||||
pendingIntent = intentManager
|
||||
.createFido2GetCredentialPendingIntent(
|
||||
action = GET_PASSKEY_INTENT,
|
||||
userId = userId,
|
||||
credentialId = fido2AutofillView.credentialId.toString(),
|
||||
cipherId = fido2AutofillView.cipherId,
|
||||
isUserVerified = isUserVerified,
|
||||
requestCode = Random.nextInt(),
|
||||
),
|
||||
pendingIntent = pendingIntentManager.createFido2GetCredentialPendingIntent(
|
||||
userId = userId,
|
||||
credentialId = fido2AutofillView.credentialId.toString(),
|
||||
cipherId = fido2AutofillView.cipherId,
|
||||
isUserVerified = isUserVerified,
|
||||
),
|
||||
beginGetPublicKeyCredentialOption = option,
|
||||
)
|
||||
.setIcon(
|
||||
@ -106,14 +100,11 @@ class CredentialEntryBuilderImpl(
|
||||
context = context,
|
||||
username = cipherView.login?.username
|
||||
?: context.getString(BitwardenString.no_username),
|
||||
pendingIntent = intentManager
|
||||
.createPasswordGetCredentialPendingIntent(
|
||||
action = GET_PASSWORD_INTENT,
|
||||
userId = userId,
|
||||
cipherId = cipherView.id,
|
||||
isUserVerified = isUserVerified,
|
||||
requestCode = Random.nextInt(),
|
||||
),
|
||||
pendingIntent = pendingIntentManager.createPasswordGetCredentialPendingIntent(
|
||||
userId = userId,
|
||||
cipherId = cipherView.id,
|
||||
isUserVerified = isUserVerified,
|
||||
),
|
||||
beginGetPasswordOption = option,
|
||||
)
|
||||
.setDisplayName(cipherView.name)
|
||||
|
||||
@ -12,6 +12,8 @@ import com.x8bit.bitwarden.data.credentials.builder.CredentialEntryBuilderImpl
|
||||
import com.x8bit.bitwarden.data.credentials.datasource.disk.PrivilegedAppDiskSource
|
||||
import com.x8bit.bitwarden.data.credentials.manager.BitwardenCredentialManager
|
||||
import com.x8bit.bitwarden.data.credentials.manager.BitwardenCredentialManagerImpl
|
||||
import com.x8bit.bitwarden.data.credentials.manager.CredentialManagerPendingIntentManager
|
||||
import com.x8bit.bitwarden.data.credentials.manager.CredentialManagerPendingIntentManagerImpl
|
||||
import com.x8bit.bitwarden.data.credentials.manager.OriginManager
|
||||
import com.x8bit.bitwarden.data.credentials.manager.OriginManagerImpl
|
||||
import com.x8bit.bitwarden.data.credentials.parser.RelyingPartyParser
|
||||
@ -26,7 +28,6 @@ import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.ciphermatching.CipherMatchingManager
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource
|
||||
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
@ -51,7 +52,7 @@ object CredentialProviderModule {
|
||||
authRepository: AuthRepository,
|
||||
bitwardenCredentialManager: BitwardenCredentialManager,
|
||||
dispatcherManager: DispatcherManager,
|
||||
intentManager: IntentManager,
|
||||
pendingIntentManager: CredentialManagerPendingIntentManager,
|
||||
biometricsEncryptionManager: BiometricsEncryptionManager,
|
||||
clock: Clock,
|
||||
): CredentialProviderProcessor =
|
||||
@ -59,7 +60,7 @@ object CredentialProviderModule {
|
||||
context = context,
|
||||
authRepository = authRepository,
|
||||
bitwardenCredentialManager = bitwardenCredentialManager,
|
||||
intentManager = intentManager,
|
||||
pendingIntentManager = pendingIntentManager,
|
||||
clock = clock,
|
||||
biometricsEncryptionManager = biometricsEncryptionManager,
|
||||
dispatcherManager = dispatcherManager,
|
||||
@ -105,11 +106,11 @@ object CredentialProviderModule {
|
||||
@Singleton
|
||||
fun provideCredentialEntryBuilder(
|
||||
@ApplicationContext context: Context,
|
||||
intentManager: IntentManager,
|
||||
pendingIntentManager: CredentialManagerPendingIntentManager,
|
||||
biometricsEncryptionManager: BiometricsEncryptionManager,
|
||||
): CredentialEntryBuilder = CredentialEntryBuilderImpl(
|
||||
context = context,
|
||||
intentManager = intentManager,
|
||||
pendingIntentManager = pendingIntentManager,
|
||||
biometricsEncryptionManager = biometricsEncryptionManager,
|
||||
)
|
||||
|
||||
@ -132,4 +133,13 @@ object CredentialProviderModule {
|
||||
fun provideRelyingPartyParser(
|
||||
json: Json,
|
||||
): RelyingPartyParser = RelyingPartyParserImpl(json)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideCredentialManagerPendingIntentManager(
|
||||
@ApplicationContext context: Context,
|
||||
): CredentialManagerPendingIntentManager =
|
||||
CredentialManagerPendingIntentManagerImpl(
|
||||
context = context,
|
||||
)
|
||||
}
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
package com.x8bit.bitwarden.data.credentials.manager
|
||||
|
||||
import android.app.PendingIntent
|
||||
|
||||
/**
|
||||
* Key for the user id included in Credential provider "create entries".
|
||||
*
|
||||
* @see CredentialManagerPendingIntentManager.createFido2CreationPendingIntent
|
||||
*/
|
||||
const val EXTRA_KEY_USER_ID: String = "user_id"
|
||||
|
||||
/**
|
||||
* Key for the credential id included in FIDO 2 provider "get entries".
|
||||
*
|
||||
* @see CredentialManagerPendingIntentManager.createFido2GetCredentialPendingIntent
|
||||
*/
|
||||
const val EXTRA_KEY_CREDENTIAL_ID: String = "credential_id"
|
||||
|
||||
/**
|
||||
* Key for the cipher id included in FIDO 2 provider "get entries".
|
||||
*
|
||||
* @see CredentialManagerPendingIntentManager.createFido2GetCredentialPendingIntent
|
||||
*/
|
||||
const val EXTRA_KEY_CIPHER_ID: String = "cipher_id"
|
||||
|
||||
/**
|
||||
* Key for the user verification performed during vault unlock while
|
||||
* processing a Credential request.
|
||||
*/
|
||||
const val EXTRA_KEY_UV_PERFORMED_DURING_UNLOCK: String = "uv_performed_during_unlock"
|
||||
|
||||
/**
|
||||
* A manager class for creating pending intents used in credential management operations.
|
||||
*/
|
||||
interface CredentialManagerPendingIntentManager {
|
||||
|
||||
/**
|
||||
* Creates a pending intent to use when providing options for FIDO 2 credential creation.
|
||||
*/
|
||||
fun createFido2CreationPendingIntent(
|
||||
userId: String,
|
||||
): PendingIntent
|
||||
|
||||
/**
|
||||
* Creates a pending intent to use when providing options for FIDO 2 credential filling.
|
||||
*/
|
||||
fun createFido2GetCredentialPendingIntent(
|
||||
userId: String,
|
||||
credentialId: String,
|
||||
cipherId: String,
|
||||
isUserVerified: Boolean,
|
||||
): PendingIntent
|
||||
|
||||
/**
|
||||
* Creates a pending intent to use when providing unlock options for FIDO 2 credential filling.
|
||||
*/
|
||||
fun createFido2UnlockPendingIntent(
|
||||
userId: String,
|
||||
): PendingIntent
|
||||
|
||||
/**
|
||||
* Creates a pending intent to use when providing options for Password credential filling.
|
||||
*/
|
||||
fun createPasswordGetCredentialPendingIntent(
|
||||
userId: String,
|
||||
cipherId: String?,
|
||||
isUserVerified: Boolean,
|
||||
): PendingIntent
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
package com.x8bit.bitwarden.data.credentials.manager
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.bitwarden.annotation.OmitFromCoverage
|
||||
import com.x8bit.bitwarden.data.autofill.util.toPendingIntentMutabilityFlag
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
* Primary implementation of [CredentialManagerPendingIntentManager].
|
||||
*/
|
||||
@OmitFromCoverage
|
||||
class CredentialManagerPendingIntentManagerImpl(
|
||||
private val context: Context,
|
||||
) : CredentialManagerPendingIntentManager {
|
||||
|
||||
/**
|
||||
* Creates a pending intent to use when providing options for FIDO 2 credential creation.
|
||||
*/
|
||||
override fun createFido2CreationPendingIntent(
|
||||
userId: String,
|
||||
): PendingIntent {
|
||||
val intent = Intent(CREATE_PASSKEY_ACTION)
|
||||
.setPackage(context.packageName)
|
||||
.putExtra(EXTRA_KEY_USER_ID, userId)
|
||||
|
||||
return PendingIntent.getActivity(
|
||||
/* context = */ context,
|
||||
/* requestCode = */ Random.nextInt(),
|
||||
/* intent = */ intent,
|
||||
/* flags = */ PendingIntent.FLAG_UPDATE_CURRENT.toPendingIntentMutabilityFlag(),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a pending intent to use when providing options for FIDO 2 credential filling.
|
||||
*/
|
||||
override fun createFido2GetCredentialPendingIntent(
|
||||
userId: String,
|
||||
credentialId: String,
|
||||
cipherId: String,
|
||||
isUserVerified: Boolean,
|
||||
): PendingIntent {
|
||||
val intent = Intent(GET_PASSKEY_ACTION)
|
||||
.setPackage(context.packageName)
|
||||
.putExtra(EXTRA_KEY_USER_ID, userId)
|
||||
.putExtra(EXTRA_KEY_CREDENTIAL_ID, credentialId)
|
||||
.putExtra(EXTRA_KEY_CIPHER_ID, cipherId)
|
||||
.putExtra(EXTRA_KEY_UV_PERFORMED_DURING_UNLOCK, isUserVerified)
|
||||
|
||||
return PendingIntent.getActivity(
|
||||
/* context = */ context,
|
||||
/* requestCode = */ Random.nextInt(),
|
||||
/* intent = */ intent,
|
||||
/* flags = */ PendingIntent.FLAG_UPDATE_CURRENT.toPendingIntentMutabilityFlag(),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a pending intent to use when providing unlock options for FIDO 2 credential filling.
|
||||
*/
|
||||
override fun createFido2UnlockPendingIntent(
|
||||
userId: String,
|
||||
): PendingIntent {
|
||||
val intent = Intent(UNLOCK_ACCOUNT_ACTION)
|
||||
.setPackage(context.packageName)
|
||||
.putExtra(EXTRA_KEY_USER_ID, userId)
|
||||
|
||||
return PendingIntent.getActivity(
|
||||
/* context = */ context,
|
||||
/* requestCode = */ Random.nextInt(),
|
||||
/* intent = */ intent,
|
||||
/* flags = */ PendingIntent.FLAG_UPDATE_CURRENT.toPendingIntentMutabilityFlag(),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a pending intent to use when providing options for Password credential filling.
|
||||
*/
|
||||
override fun createPasswordGetCredentialPendingIntent(
|
||||
userId: String,
|
||||
cipherId: String?,
|
||||
isUserVerified: Boolean,
|
||||
): PendingIntent {
|
||||
val intent = Intent(GET_PASSWORD_ACTION)
|
||||
.setPackage(context.packageName)
|
||||
.putExtra(EXTRA_KEY_USER_ID, userId)
|
||||
.putExtra(EXTRA_KEY_CIPHER_ID, cipherId)
|
||||
.putExtra(EXTRA_KEY_UV_PERFORMED_DURING_UNLOCK, isUserVerified)
|
||||
|
||||
return PendingIntent.getActivity(
|
||||
/* context = */ context,
|
||||
/* requestCode = */ Random.nextInt(),
|
||||
/* intent = */ intent,
|
||||
/* flags = */ PendingIntent.FLAG_UPDATE_CURRENT.toPendingIntentMutabilityFlag(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private const val CREATE_PASSKEY_ACTION = "com.x8bit.bitwarden.credentials.ACTION_CREATE_PASSKEY"
|
||||
private const val UNLOCK_ACCOUNT_ACTION = "com.x8bit.bitwarden.credentials.ACTION_UNLOCK_ACCOUNT"
|
||||
private const val GET_PASSKEY_ACTION = "com.x8bit.bitwarden.credentials.ACTION_GET_PASSKEY"
|
||||
private const val GET_PASSWORD_ACTION = "com.x8bit.bitwarden.credentials.ACTION_GET_PASSWORD"
|
||||
@ -31,20 +31,14 @@ import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
||||
import com.x8bit.bitwarden.data.credentials.manager.BitwardenCredentialManager
|
||||
import com.x8bit.bitwarden.data.credentials.manager.CredentialManagerPendingIntentManager
|
||||
import com.x8bit.bitwarden.data.credentials.model.GetCredentialsRequest
|
||||
import com.x8bit.bitwarden.data.platform.manager.BiometricsEncryptionManager
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.time.Clock
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import javax.crypto.Cipher
|
||||
|
||||
private const val CREATE_PASSKEY_INTENT = "com.x8bit.bitwarden.credentials.ACTION_CREATE_PASSKEY"
|
||||
const val GET_PASSKEY_INTENT = "com.x8bit.bitwarden.credentials.ACTION_GET_PASSKEY"
|
||||
const val GET_PASSWORD_INTENT = "com.x8bit.bitwarden.credentials.ACTION_GET_PASSWORD"
|
||||
const val UNLOCK_ACCOUNT_INTENT = "com.x8bit.bitwarden.credentials.ACTION_UNLOCK_ACCOUNT"
|
||||
|
||||
/**
|
||||
* The default implementation of [CredentialProviderProcessor]. Its purpose is to handle
|
||||
* [CredentialManager] requests from other applications.
|
||||
@ -55,13 +49,12 @@ class CredentialProviderProcessorImpl(
|
||||
private val context: Context,
|
||||
private val authRepository: AuthRepository,
|
||||
private val bitwardenCredentialManager: BitwardenCredentialManager,
|
||||
private val intentManager: IntentManager,
|
||||
private val pendingIntentManager: CredentialManagerPendingIntentManager,
|
||||
private val clock: Clock,
|
||||
private val biometricsEncryptionManager: BiometricsEncryptionManager,
|
||||
dispatcherManager: DispatcherManager,
|
||||
) : CredentialProviderProcessor {
|
||||
|
||||
private val requestCode = AtomicInteger()
|
||||
private val ioScope = CoroutineScope(dispatcherManager.io)
|
||||
|
||||
override fun processCreateCredentialRequest(
|
||||
@ -104,10 +97,8 @@ class CredentialProviderProcessorImpl(
|
||||
if (!userState.activeAccount.isVaultUnlocked) {
|
||||
val authenticationAction = AuthenticationAction(
|
||||
title = context.getString(BitwardenString.unlock),
|
||||
pendingIntent = intentManager.createFido2UnlockPendingIntent(
|
||||
action = UNLOCK_ACCOUNT_INTENT,
|
||||
pendingIntent = pendingIntentManager.createFido2UnlockPendingIntent(
|
||||
userId = userState.activeUserId,
|
||||
requestCode = requestCode.getAndIncrement(),
|
||||
),
|
||||
)
|
||||
|
||||
@ -182,10 +173,8 @@ class CredentialProviderProcessorImpl(
|
||||
val entryBuilder = CreateEntry
|
||||
.Builder(
|
||||
accountName = accountName,
|
||||
pendingIntent = intentManager.createFido2CreationPendingIntent(
|
||||
action = CREATE_PASSKEY_INTENT,
|
||||
pendingIntent = pendingIntentManager.createFido2CreationPendingIntent(
|
||||
userId = userId,
|
||||
requestCode = requestCode.getAndIncrement(),
|
||||
),
|
||||
)
|
||||
.setDescription(
|
||||
|
||||
@ -8,14 +8,14 @@ import androidx.credentials.provider.PendingIntentHandler
|
||||
import androidx.credentials.provider.ProviderCreateCredentialRequest
|
||||
import androidx.credentials.provider.ProviderGetCredentialRequest
|
||||
import com.bitwarden.core.util.isBuildVersionAtLeast
|
||||
import com.x8bit.bitwarden.data.credentials.manager.EXTRA_KEY_CIPHER_ID
|
||||
import com.x8bit.bitwarden.data.credentials.manager.EXTRA_KEY_CREDENTIAL_ID
|
||||
import com.x8bit.bitwarden.data.credentials.manager.EXTRA_KEY_USER_ID
|
||||
import com.x8bit.bitwarden.data.credentials.manager.EXTRA_KEY_UV_PERFORMED_DURING_UNLOCK
|
||||
import com.x8bit.bitwarden.data.credentials.model.CreateCredentialRequest
|
||||
import com.x8bit.bitwarden.data.credentials.model.Fido2CredentialAssertionRequest
|
||||
import com.x8bit.bitwarden.data.credentials.model.GetCredentialsRequest
|
||||
import com.x8bit.bitwarden.data.credentials.model.ProviderGetPasswordCredentialRequest
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.EXTRA_KEY_CIPHER_ID
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.EXTRA_KEY_CREDENTIAL_ID
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.EXTRA_KEY_USER_ID
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.EXTRA_KEY_UV_PERFORMED_DURING_UNLOCK
|
||||
|
||||
/**
|
||||
* Checks if this [Intent] contains a [CreateCredentialRequest] related to an ongoing
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package com.x8bit.bitwarden.ui.platform.manager.intent
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
@ -9,9 +8,6 @@ import androidx.activity.compose.ManagedActivityResultLauncher
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.credentials.provider.AuthenticationAction
|
||||
import androidx.credentials.provider.CreateEntry
|
||||
import androidx.credentials.provider.CredentialEntry
|
||||
import com.x8bit.bitwarden.data.autofill.model.browser.BrowserPackage
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@ -106,52 +102,6 @@ interface IntentManager {
|
||||
*/
|
||||
fun createDocumentIntent(fileName: String): Intent
|
||||
|
||||
/**
|
||||
* Creates a pending intent to use when providing [CreateEntry]
|
||||
* instances for FIDO 2 credential creation.
|
||||
*/
|
||||
fun createFido2CreationPendingIntent(
|
||||
action: String,
|
||||
userId: String,
|
||||
requestCode: Int,
|
||||
): PendingIntent
|
||||
|
||||
/**
|
||||
* Creates a pending intent to use when providing
|
||||
* [CredentialEntry] instances for FIDO 2 credential filling.
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
fun createFido2GetCredentialPendingIntent(
|
||||
action: String,
|
||||
userId: String,
|
||||
credentialId: String,
|
||||
cipherId: String,
|
||||
isUserVerified: Boolean,
|
||||
requestCode: Int,
|
||||
): PendingIntent
|
||||
|
||||
/**
|
||||
* Creates a pending intent to use when providing
|
||||
* [AuthenticationAction] instances for FIDO 2 credential filling.
|
||||
*/
|
||||
fun createFido2UnlockPendingIntent(
|
||||
action: String,
|
||||
userId: String,
|
||||
requestCode: Int,
|
||||
): PendingIntent
|
||||
|
||||
/**
|
||||
* Creates a pending intent to use when providing
|
||||
* [CredentialEntry] instances for Password credential filling.
|
||||
*/
|
||||
fun createPasswordGetCredentialPendingIntent(
|
||||
action: String,
|
||||
userId: String,
|
||||
cipherId: String?,
|
||||
isUserVerified: Boolean,
|
||||
requestCode: Int,
|
||||
): PendingIntent
|
||||
|
||||
/**
|
||||
* Open the default email app on device.
|
||||
*/
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package com.x8bit.bitwarden.ui.platform.manager.intent
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.PendingIntent
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
@ -29,7 +28,6 @@ import com.bitwarden.core.util.isBuildVersionAtLeast
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.x8bit.bitwarden.BuildConfig
|
||||
import com.x8bit.bitwarden.data.autofill.model.browser.BrowserPackage
|
||||
import com.x8bit.bitwarden.data.autofill.util.toPendingIntentMutabilityFlag
|
||||
import java.io.File
|
||||
import java.time.Clock
|
||||
|
||||
@ -50,33 +48,6 @@ private const val TEMP_CAMERA_IMAGE_NAME: String = "temp_camera_image.jpg"
|
||||
*/
|
||||
private const val TEMP_CAMERA_IMAGE_DIR: String = "camera_temp"
|
||||
|
||||
/**
|
||||
* Key for the user id included in Credential provider "create entries".
|
||||
*
|
||||
* @see IntentManager.createFido2CreationPendingIntent
|
||||
*/
|
||||
const val EXTRA_KEY_USER_ID: String = "user_id"
|
||||
|
||||
/**
|
||||
* Key for the credential id included in FIDO 2 provider "get entries".
|
||||
*
|
||||
* @see IntentManager.createFido2GetCredentialPendingIntent
|
||||
*/
|
||||
const val EXTRA_KEY_CREDENTIAL_ID: String = "credential_id"
|
||||
|
||||
/**
|
||||
* Key for the cipher id included in FIDO 2 provider "get entries".
|
||||
*
|
||||
* @see IntentManager.createFido2GetCredentialPendingIntent
|
||||
*/
|
||||
const val EXTRA_KEY_CIPHER_ID: String = "cipher_id"
|
||||
|
||||
/**
|
||||
* Key for the user verification performed during vault unlock while
|
||||
* processing a Credential request.
|
||||
*/
|
||||
const val EXTRA_KEY_UV_PERFORMED_DURING_UNLOCK: String = "uv_performed_during_unlock"
|
||||
|
||||
/**
|
||||
* The default implementation of the [IntentManager] for simplifying the handling of Android
|
||||
* Intents within a given context.
|
||||
@ -288,84 +259,6 @@ class IntentManagerImpl(
|
||||
putExtra(Intent.EXTRA_TITLE, fileName)
|
||||
}
|
||||
|
||||
override fun createFido2CreationPendingIntent(
|
||||
action: String,
|
||||
userId: String,
|
||||
requestCode: Int,
|
||||
): PendingIntent {
|
||||
val intent = Intent(action)
|
||||
.setPackage(context.packageName)
|
||||
.putExtra(EXTRA_KEY_USER_ID, userId)
|
||||
|
||||
return PendingIntent.getActivity(
|
||||
/* context = */ context,
|
||||
/* requestCode = */ requestCode,
|
||||
/* intent = */ intent,
|
||||
/* flags = */ PendingIntent.FLAG_UPDATE_CURRENT.toPendingIntentMutabilityFlag(),
|
||||
)
|
||||
}
|
||||
|
||||
override fun createFido2GetCredentialPendingIntent(
|
||||
action: String,
|
||||
userId: String,
|
||||
credentialId: String,
|
||||
cipherId: String,
|
||||
isUserVerified: Boolean,
|
||||
requestCode: Int,
|
||||
): PendingIntent {
|
||||
val intent = Intent(action)
|
||||
.setPackage(context.packageName)
|
||||
.putExtra(EXTRA_KEY_USER_ID, userId)
|
||||
.putExtra(EXTRA_KEY_CREDENTIAL_ID, credentialId)
|
||||
.putExtra(EXTRA_KEY_CIPHER_ID, cipherId)
|
||||
.putExtra(EXTRA_KEY_UV_PERFORMED_DURING_UNLOCK, isUserVerified)
|
||||
|
||||
return PendingIntent.getActivity(
|
||||
/* context = */ context,
|
||||
/* requestCode = */ requestCode,
|
||||
/* intent = */ intent,
|
||||
/* flags = */ PendingIntent.FLAG_UPDATE_CURRENT.toPendingIntentMutabilityFlag(),
|
||||
)
|
||||
}
|
||||
|
||||
override fun createFido2UnlockPendingIntent(
|
||||
action: String,
|
||||
userId: String,
|
||||
requestCode: Int,
|
||||
): PendingIntent {
|
||||
val intent = Intent(action)
|
||||
.setPackage(context.packageName)
|
||||
.putExtra(EXTRA_KEY_USER_ID, userId)
|
||||
|
||||
return PendingIntent.getActivity(
|
||||
/* context = */ context,
|
||||
/* requestCode = */ requestCode,
|
||||
/* intent = */ intent,
|
||||
/* flags = */ PendingIntent.FLAG_UPDATE_CURRENT.toPendingIntentMutabilityFlag(),
|
||||
)
|
||||
}
|
||||
|
||||
override fun createPasswordGetCredentialPendingIntent(
|
||||
action: String,
|
||||
userId: String,
|
||||
cipherId: String?,
|
||||
isUserVerified: Boolean,
|
||||
requestCode: Int,
|
||||
): PendingIntent {
|
||||
val intent = Intent(action)
|
||||
.setPackage(context.packageName)
|
||||
.putExtra(EXTRA_KEY_USER_ID, userId)
|
||||
.putExtra(EXTRA_KEY_CIPHER_ID, cipherId)
|
||||
.putExtra(EXTRA_KEY_UV_PERFORMED_DURING_UNLOCK, isUserVerified)
|
||||
|
||||
return PendingIntent.getActivity(
|
||||
/* context = */ context,
|
||||
/* requestCode = */ requestCode,
|
||||
/* intent = */ intent,
|
||||
/* flags = */ PendingIntent.FLAG_UPDATE_CURRENT.toPendingIntentMutabilityFlag(),
|
||||
)
|
||||
}
|
||||
|
||||
override fun startDefaultEmailApplication() {
|
||||
val intent = Intent(Intent.ACTION_MAIN)
|
||||
intent.addCategory(Intent.CATEGORY_APP_EMAIL)
|
||||
|
||||
@ -12,12 +12,12 @@ import com.bitwarden.core.util.isBuildVersionAtLeast
|
||||
import com.bitwarden.fido.Fido2CredentialAutofillView
|
||||
import com.bitwarden.vault.CipherListView
|
||||
import com.bitwarden.vault.CipherListViewType
|
||||
import com.x8bit.bitwarden.data.credentials.manager.CredentialManagerPendingIntentManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.BiometricsEncryptionManager
|
||||
import com.x8bit.bitwarden.data.util.mockBuilder
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCipherListView
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockFido2CredentialAutofillView
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockLoginListView
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkConstructor
|
||||
@ -36,23 +36,19 @@ class CredentialEntryBuilderTest {
|
||||
private val mockContext = mockk<Context>()
|
||||
private val mockGetPublicKeyCredentialIntent = mockk<PendingIntent>(relaxed = true)
|
||||
private val mockGetPasswordCredentialIntent = mockk<PendingIntent>(relaxed = true)
|
||||
private val mockIntentManager = mockk<IntentManager> {
|
||||
private val mockPendingIntentManager = mockk<CredentialManagerPendingIntentManager> {
|
||||
every {
|
||||
createFido2GetCredentialPendingIntent(
|
||||
action = any(),
|
||||
userId = any(),
|
||||
cipherId = any(),
|
||||
credentialId = any(),
|
||||
requestCode = any(),
|
||||
isUserVerified = any(),
|
||||
)
|
||||
} returns mockGetPublicKeyCredentialIntent
|
||||
every {
|
||||
createPasswordGetCredentialPendingIntent(
|
||||
action = any(),
|
||||
userId = any(),
|
||||
cipherId = any(),
|
||||
requestCode = any(),
|
||||
isUserVerified = any(),
|
||||
)
|
||||
} returns mockGetPasswordCredentialIntent
|
||||
@ -62,7 +58,7 @@ class CredentialEntryBuilderTest {
|
||||
private val mockBeginGetPasswordOption = mockk<BeginGetPasswordOption>()
|
||||
private val credentialEntryBuilder = CredentialEntryBuilderImpl(
|
||||
context = mockContext,
|
||||
intentManager = mockIntentManager,
|
||||
pendingIntentManager = mockPendingIntentManager,
|
||||
biometricsEncryptionManager = mockBiometricsEncryptionManager,
|
||||
)
|
||||
private val mockPublicKeyCredentialEntry = mockk<PublicKeyCredentialEntry>(relaxed = true)
|
||||
@ -155,12 +151,10 @@ class CredentialEntryBuilderTest {
|
||||
assertTrue(result.isNotEmpty())
|
||||
|
||||
verify {
|
||||
mockIntentManager.createFido2GetCredentialPendingIntent(
|
||||
action = "com.x8bit.bitwarden.credentials.ACTION_GET_PASSKEY",
|
||||
mockPendingIntentManager.createFido2GetCredentialPendingIntent(
|
||||
userId = "userId",
|
||||
cipherId = "mockCipherId-1",
|
||||
credentialId = fido2AutofillViews.first().credentialId.toString(),
|
||||
requestCode = any(),
|
||||
isUserVerified = false,
|
||||
)
|
||||
|
||||
@ -326,11 +320,9 @@ class CredentialEntryBuilderTest {
|
||||
assertTrue(result.isNotEmpty())
|
||||
|
||||
verify {
|
||||
mockIntentManager.createPasswordGetCredentialPendingIntent(
|
||||
action = "com.x8bit.bitwarden.credentials.ACTION_GET_PASSWORD",
|
||||
mockPendingIntentManager.createPasswordGetCredentialPendingIntent(
|
||||
userId = "userId",
|
||||
cipherId = "mockId-1",
|
||||
requestCode = any(),
|
||||
isUserVerified = false,
|
||||
)
|
||||
|
||||
|
||||
@ -31,9 +31,9 @@ import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType
|
||||
import com.x8bit.bitwarden.data.credentials.manager.BitwardenCredentialManager
|
||||
import com.x8bit.bitwarden.data.credentials.manager.CredentialManagerPendingIntentManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.BiometricsEncryptionManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.every
|
||||
import io.mockk.just
|
||||
@ -69,7 +69,7 @@ class CredentialProviderProcessorTest {
|
||||
private val bitwardenCredentialManager: BitwardenCredentialManager = mockk {
|
||||
coEvery { getCredentialEntries(any()) } returns credentialEntries.asSuccess()
|
||||
}
|
||||
private val intentManager: IntentManager = mockk()
|
||||
private val pendingIntentManager: CredentialManagerPendingIntentManager = mockk()
|
||||
private val dispatcherManager: DispatcherManager = FakeDispatcherManager()
|
||||
private val biometricsEncryptionManager: BiometricsEncryptionManager = mockk()
|
||||
private val cancellationSignal: CancellationSignal = mockk()
|
||||
@ -82,7 +82,7 @@ class CredentialProviderProcessorTest {
|
||||
context = context,
|
||||
authRepository = authRepository,
|
||||
bitwardenCredentialManager = bitwardenCredentialManager,
|
||||
intentManager = intentManager,
|
||||
pendingIntentManager = pendingIntentManager,
|
||||
clock = clock,
|
||||
biometricsEncryptionManager = biometricsEncryptionManager,
|
||||
dispatcherManager = dispatcherManager,
|
||||
@ -220,10 +220,8 @@ class CredentialProviderProcessorTest {
|
||||
every { context.packageName } returns "com.x8bit.bitwarden"
|
||||
every { context.getString(any(), any()) } returns "mockDescription"
|
||||
every {
|
||||
intentManager.createFido2CreationPendingIntent(
|
||||
action = any(),
|
||||
pendingIntentManager.createFido2CreationPendingIntent(
|
||||
userId = any(),
|
||||
requestCode = any(),
|
||||
)
|
||||
} returns mockIntent
|
||||
every {
|
||||
@ -270,10 +268,8 @@ class CredentialProviderProcessorTest {
|
||||
} returns "{\"mockJsonRequest\":1}"
|
||||
every { callback.onResult(capture(captureSlot)) } just runs
|
||||
every {
|
||||
intentManager.createFido2CreationPendingIntent(
|
||||
action = any(),
|
||||
pendingIntentManager.createFido2CreationPendingIntent(
|
||||
userId = any(),
|
||||
requestCode = any(),
|
||||
)
|
||||
} returns mockIntent
|
||||
every {
|
||||
@ -383,10 +379,8 @@ class CredentialProviderProcessorTest {
|
||||
every { callback.onResult(capture(captureSlot)) } just runs
|
||||
every { context.getString(any()) } returns "mockTitle"
|
||||
every {
|
||||
intentManager.createFido2UnlockPendingIntent(
|
||||
action = "com.x8bit.bitwarden.credentials.ACTION_UNLOCK_ACCOUNT",
|
||||
pendingIntentManager.createFido2UnlockPendingIntent(
|
||||
userId = "mockUserId-1",
|
||||
requestCode = any(),
|
||||
)
|
||||
} returns mockIntent
|
||||
|
||||
@ -404,10 +398,8 @@ class CredentialProviderProcessorTest {
|
||||
verify(exactly = 0) { callback.onError(any()) }
|
||||
verify(exactly = 1) {
|
||||
callback.onResult(any())
|
||||
intentManager.createFido2UnlockPendingIntent(
|
||||
action = "com.x8bit.bitwarden.credentials.ACTION_UNLOCK_ACCOUNT",
|
||||
pendingIntentManager.createFido2UnlockPendingIntent(
|
||||
userId = "mockUserId-1",
|
||||
requestCode = any(),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -8,10 +8,10 @@ import androidx.credentials.provider.PendingIntentHandler
|
||||
import androidx.credentials.provider.ProviderCreateCredentialRequest
|
||||
import androidx.credentials.provider.ProviderGetCredentialRequest
|
||||
import com.bitwarden.core.util.isBuildVersionAtLeast
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.EXTRA_KEY_CIPHER_ID
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.EXTRA_KEY_CREDENTIAL_ID
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.EXTRA_KEY_USER_ID
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.EXTRA_KEY_UV_PERFORMED_DURING_UNLOCK
|
||||
import com.x8bit.bitwarden.data.credentials.manager.EXTRA_KEY_CIPHER_ID
|
||||
import com.x8bit.bitwarden.data.credentials.manager.EXTRA_KEY_CREDENTIAL_ID
|
||||
import com.x8bit.bitwarden.data.credentials.manager.EXTRA_KEY_USER_ID
|
||||
import com.x8bit.bitwarden.data.credentials.manager.EXTRA_KEY_UV_PERFORMED_DURING_UNLOCK
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkObject
|
||||
|
||||
@ -11,8 +11,7 @@ import androidx.credentials.provider.PasswordCredentialEntry
|
||||
import androidx.credentials.provider.PendingIntentHandler
|
||||
import androidx.credentials.provider.PublicKeyCredentialEntry
|
||||
import com.bitwarden.ui.util.asText
|
||||
import com.x8bit.bitwarden.data.credentials.processor.GET_PASSKEY_INTENT
|
||||
import com.x8bit.bitwarden.data.credentials.processor.GET_PASSWORD_INTENT
|
||||
import com.x8bit.bitwarden.data.credentials.manager.CredentialManagerPendingIntentManager
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockFido2CredentialAutofillView
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockLoginView
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockPasswordCredentialAutofillCipherLogin
|
||||
@ -20,7 +19,6 @@ import com.x8bit.bitwarden.ui.credentials.manager.model.AssertFido2CredentialRes
|
||||
import com.x8bit.bitwarden.ui.credentials.manager.model.GetCredentialsResult
|
||||
import com.x8bit.bitwarden.ui.credentials.manager.model.GetPasswordCredentialResult
|
||||
import com.x8bit.bitwarden.ui.credentials.manager.model.RegisterFido2CredentialResult
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
|
||||
import io.mockk.Called
|
||||
import io.mockk.MockKVerificationScope
|
||||
import io.mockk.Ordering
|
||||
@ -107,7 +105,7 @@ class CredentialProviderCompletionManagerTest {
|
||||
@Nested
|
||||
inner class DefaultImplementation {
|
||||
|
||||
private val mockIntentManager = mockk<IntentManager>()
|
||||
private val mockPendingIntentManager = mockk<CredentialManagerPendingIntentManager>()
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
@ -274,13 +272,11 @@ class CredentialProviderCompletionManagerTest {
|
||||
val mockFido2AutofillView = createMockFido2CredentialAutofillView(number = 1)
|
||||
|
||||
every {
|
||||
mockIntentManager.createFido2GetCredentialPendingIntent(
|
||||
action = GET_PASSKEY_INTENT,
|
||||
mockPendingIntentManager.createFido2GetCredentialPendingIntent(
|
||||
userId = "mockUserId",
|
||||
credentialId = mockFido2AutofillView.credentialId.toString(),
|
||||
cipherId = mockFido2AutofillView.cipherId,
|
||||
isUserVerified = false,
|
||||
requestCode = any(),
|
||||
)
|
||||
} returns mockk()
|
||||
every { mockActivity.getString(any()) } returns "No username"
|
||||
@ -320,12 +316,10 @@ class CredentialProviderCompletionManagerTest {
|
||||
val mockPasswordAutofillView = createMockPasswordCredentialAutofillCipherLogin()
|
||||
|
||||
every {
|
||||
mockIntentManager.createPasswordGetCredentialPendingIntent(
|
||||
action = GET_PASSWORD_INTENT,
|
||||
mockPendingIntentManager.createPasswordGetCredentialPendingIntent(
|
||||
userId = "mockUserId",
|
||||
cipherId = mockPasswordAutofillView.cipherId,
|
||||
isUserVerified = false,
|
||||
requestCode = any(),
|
||||
)
|
||||
} returns mockk()
|
||||
every { mockActivity.getString(any()) } returns "No username"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user