Merge "Fix some bugs for the create flow"

This commit is contained in:
Qinmei Du
2022-12-07 06:11:58 +00:00
committed by Android (Google) Code Review
4 changed files with 89 additions and 58 deletions

View File

@@ -40,12 +40,9 @@ import android.os.Binder
import android.os.Bundle
import android.os.ResultReceiver
import android.service.credentials.CredentialProviderService
import com.android.credentialmanager.createflow.ActiveEntry
import com.android.credentialmanager.createflow.CreateCredentialUiState
import com.android.credentialmanager.createflow.CreateScreenState
import com.android.credentialmanager.createflow.EnabledProviderInfo
import com.android.credentialmanager.createflow.RemoteInfo
import com.android.credentialmanager.createflow.RequestDisplayInfo
import com.android.credentialmanager.getflow.GetCredentialUiState
import com.android.credentialmanager.getflow.GetScreenState
import com.android.credentialmanager.jetpack.developer.CreatePasswordRequest.Companion.toBundle
@@ -146,20 +143,30 @@ class CredentialManagerRepo(
providerDisabledList, context)
var defaultProvider: EnabledProviderInfo? = null
var remoteEntry: RemoteInfo? = null
var createOptionSize = 0
var lastSeenProviderWithNonEmptyCreateOptions: EnabledProviderInfo? = null
providerEnabledList.forEach{providerInfo -> providerInfo.createOptions =
providerInfo.createOptions.sortedWith(compareBy { it.lastUsedTimeMillis }).reversed()
if (providerInfo.isDefault) {defaultProvider = providerInfo}
if (providerInfo.remoteEntry != null) {
remoteEntry = providerInfo.remoteEntry!!
}
if (providerInfo.createOptions.isNotEmpty()) {
createOptionSize += providerInfo.createOptions.size
lastSeenProviderWithNonEmptyCreateOptions = providerInfo
}
}
return CreateCredentialUiState(
enabledProviders = providerEnabledList,
disabledProviders = providerDisabledList,
toCreateScreenState(requestDisplayInfo, defaultProvider, remoteEntry),
CreateFlowUtils.toCreateScreenState(
createOptionSize, false,
requestDisplayInfo, defaultProvider, remoteEntry),
requestDisplayInfo,
false,
toActiveEntry(defaultProvider, remoteEntry),
CreateFlowUtils.toActiveEntry(
/*defaultProvider=*/defaultProvider, createOptionSize,
lastSeenProviderWithNonEmptyCreateOptions, remoteEntry),
)
}
@@ -194,6 +201,7 @@ class CredentialManagerRepo(
.setRemoteEntry(
newRemoteEntry("key2", "subkey-1")
)
.setIsDefaultProvider(true)
.build(),
CreateCredentialProviderData
.Builder("com.dashlane")
@@ -517,38 +525,4 @@ class CredentialManagerRepo(
"tribank.us"
)
}
private fun toCreateScreenState(
requestDisplayInfo: RequestDisplayInfo,
defaultProvider: EnabledProviderInfo?,
remoteEntry: RemoteInfo?,
): CreateScreenState {
return if (
defaultProvider != null && defaultProvider.createOptions.isEmpty() && remoteEntry != null
){
CreateScreenState.EXTERNAL_ONLY_SELECTION
} else if (defaultProvider == null || defaultProvider.createOptions.isEmpty()) {
if (requestDisplayInfo.type == TYPE_PUBLIC_KEY_CREDENTIAL) {
CreateScreenState.PASSKEY_INTRO
} else {
CreateScreenState.PROVIDER_SELECTION
}
} else {
CreateScreenState.CREATION_OPTION_SELECTION
}
}
private fun toActiveEntry(
defaultProvider: EnabledProviderInfo?,
remoteEntry: RemoteInfo?,
): ActiveEntry? {
return if (
defaultProvider != null && defaultProvider.createOptions.isNotEmpty()
) {
ActiveEntry(defaultProvider, defaultProvider.createOptions.first())
} else if (
defaultProvider != null && defaultProvider.createOptions.isEmpty() && remoteEntry != null) {
ActiveEntry(defaultProvider, remoteEntry)
} else null
}
}

View File

@@ -28,6 +28,9 @@ import android.graphics.drawable.Drawable
import com.android.credentialmanager.createflow.CreateOptionInfo
import com.android.credentialmanager.createflow.RemoteInfo
import com.android.credentialmanager.createflow.RequestDisplayInfo
import com.android.credentialmanager.createflow.EnabledProviderInfo
import com.android.credentialmanager.createflow.CreateScreenState
import com.android.credentialmanager.createflow.ActiveEntry
import com.android.credentialmanager.getflow.ActionEntryInfo
import com.android.credentialmanager.getflow.AuthenticationEntryInfo
import com.android.credentialmanager.getflow.CredentialEntryInfo
@@ -36,6 +39,7 @@ import com.android.credentialmanager.getflow.RemoteEntryInfo
import com.android.credentialmanager.jetpack.developer.CreateCredentialRequest
import com.android.credentialmanager.jetpack.developer.CreatePasswordRequest
import com.android.credentialmanager.jetpack.developer.CreatePublicKeyCredentialRequest
import com.android.credentialmanager.jetpack.developer.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
import com.android.credentialmanager.jetpack.provider.ActionUi
import com.android.credentialmanager.jetpack.provider.CredentialEntryUi
import com.android.credentialmanager.jetpack.provider.SaveEntryUi
@@ -243,7 +247,8 @@ class CreateFlowUtils {
createCredentialRequestJetpack.password,
createCredentialRequestJetpack.type,
requestInfo.appPackageName,
context.getDrawable(R.drawable.ic_password)!!
context.getDrawable(R.drawable.ic_password)!!,
requestInfo.isFirstUsage
)
}
is CreatePublicKeyCredentialRequest -> {
@@ -261,7 +266,8 @@ class CreateFlowUtils {
displayName,
createCredentialRequestJetpack.type,
requestInfo.appPackageName,
context.getDrawable(R.drawable.ic_passkey)!!)
context.getDrawable(R.drawable.ic_passkey)!!,
requestInfo.isFirstUsage)
}
// TODO: correctly parsing for other sign-ins
else -> {
@@ -270,11 +276,58 @@ class CreateFlowUtils {
"Elisa Beckett",
"other-sign-ins",
requestInfo.appPackageName,
context.getDrawable(R.drawable.ic_other_sign_in)!!)
context.getDrawable(R.drawable.ic_other_sign_in)!!,
requestInfo.isFirstUsage)
}
}
}
fun toCreateScreenState(
createOptionSize: Int,
isOnPasskeyIntroStateAlready: Boolean,
requestDisplayInfo: RequestDisplayInfo,
defaultProvider: EnabledProviderInfo?,
remoteEntry: RemoteInfo?,
): CreateScreenState {
return if (requestDisplayInfo.isFirstUsage && requestDisplayInfo
.type == TYPE_PUBLIC_KEY_CREDENTIAL && !isOnPasskeyIntroStateAlready) {
CreateScreenState.PASSKEY_INTRO
} else if (
(defaultProvider == null || defaultProvider.createOptions.isEmpty()
) && createOptionSize > 1) {
CreateScreenState.PROVIDER_SELECTION
} else if (
((defaultProvider == null || defaultProvider.createOptions.isEmpty()
) && createOptionSize == 1) || (
defaultProvider != null && defaultProvider.createOptions.isNotEmpty())) {
CreateScreenState.CREATION_OPTION_SELECTION
} else if (createOptionSize == 0 && remoteEntry != null) {
CreateScreenState.EXTERNAL_ONLY_SELECTION
} else {
// TODO: properly handle error and gracefully finish itself
throw java.lang.IllegalStateException("Empty provider list.")
}
}
fun toActiveEntry(
defaultProvider: EnabledProviderInfo?,
createOptionSize: Int,
lastSeenProviderWithNonEmptyCreateOptions: EnabledProviderInfo?,
remoteEntry: RemoteInfo?,
): ActiveEntry? {
return if (
defaultProvider != null && defaultProvider.createOptions.isEmpty() && remoteEntry != null) {
ActiveEntry(defaultProvider, remoteEntry)
} else if (
defaultProvider != null && defaultProvider.createOptions.isNotEmpty()
) {
ActiveEntry(defaultProvider, defaultProvider.createOptions.first())
} else if (createOptionSize == 1) {
ActiveEntry(lastSeenProviderWithNonEmptyCreateOptions!!,
lastSeenProviderWithNonEmptyCreateOptions.createOptions.first())
} else null
}
private fun toCreationOptionInfoList(
providerId: String,
creationEntries: List<Entry>,

View File

@@ -27,6 +27,7 @@ import androidx.compose.runtime.setValue
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.android.credentialmanager.CreateFlowUtils
import com.android.credentialmanager.CredentialManagerRepo
import com.android.credentialmanager.common.DialogResult
import com.android.credentialmanager.common.ProviderActivityResult
@@ -60,24 +61,26 @@ class CreateCredentialViewModel(
fun onConfirmIntro() {
var createOptionSize = 0
var lastSeenProviderWithNonEmptyCreateOptions: EnabledProviderInfo? = null
var remoteEntry: RemoteInfo? = null
uiState.enabledProviders.forEach {
enabledProvider -> createOptionSize += enabledProvider.createOptions.size}
uiState = if (createOptionSize > 1) {
uiState.copy(
currentScreenState = CreateScreenState.PROVIDER_SELECTION,
showActiveEntryOnly = true
)
} else if (createOptionSize == 1){
uiState.copy(
currentScreenState = CreateScreenState.CREATION_OPTION_SELECTION,
showActiveEntryOnly = false,
activeEntry = ActiveEntry(uiState.enabledProviders.first(),
uiState.enabledProviders.first().createOptions.first()
)
)
} else {
throw java.lang.IllegalStateException("Empty provider list.")
enabledProvider ->
if (enabledProvider.createOptions.isNotEmpty()) {
createOptionSize += enabledProvider.createOptions.size
lastSeenProviderWithNonEmptyCreateOptions = enabledProvider
}
if (enabledProvider.remoteEntry != null) {
remoteEntry = enabledProvider.remoteEntry!!
}
}
uiState = uiState.copy(
currentScreenState = CreateFlowUtils.toCreateScreenState(
createOptionSize, true,
uiState.requestDisplayInfo, null, remoteEntry),
showActiveEntryOnly = createOptionSize > 1,
activeEntry = CreateFlowUtils.toActiveEntry(
null, createOptionSize, lastSeenProviderWithNonEmptyCreateOptions, remoteEntry),
)
}
fun getProviderInfoByName(providerName: String): EnabledProviderInfo {

View File

@@ -77,6 +77,7 @@ data class RequestDisplayInfo(
val type: String,
val appDomainName: String,
val typeIcon: Drawable,
val isFirstUsage: Boolean,
)
/**