Merge "[CredManUI] Honor preferImmediatelyAvailableCred" into udc-dev

This commit is contained in:
Helen Qin
2023-02-28 19:58:17 +00:00
committed by Android (Google) Code Review
4 changed files with 93 additions and 31 deletions

View File

@@ -45,6 +45,8 @@ import com.android.credentialmanager.getflow.GetCredentialUiState
import androidx.credentials.CreateCredentialRequest.DisplayInfo
import androidx.credentials.CreatePublicKeyCredentialRequest
import androidx.credentials.CreatePasswordRequest
import androidx.credentials.GetPasswordOption
import androidx.credentials.GetPublicKeyCredentialOption
import java.time.Instant
@@ -71,7 +73,7 @@ class CredentialManagerRepo(
requestInfo = intent.extras?.getParcelable(
RequestInfo.EXTRA_REQUEST_INFO,
RequestInfo::class.java
) ?: testCreatePasswordRequestInfo()
) ?: testCreatePasskeyRequestInfo()
val originName: String? = when (requestInfo.type) {
RequestInfo.TYPE_CREATE -> requestInfo.createCredentialRequest?.origin
@@ -120,8 +122,7 @@ class CredentialManagerRepo(
providerDisableListUiState,
defaultProviderId,
requestDisplayInfoUiState,
/** isOnPasskeyIntroStateAlready */
false,
isOnPasskeyIntroStateAlready = false,
isPasskeyFirstUse
)!!,
getCredentialUiState = null,
@@ -400,7 +401,8 @@ class CredentialManagerRepo(
" \"authenticatorSelection\": {\n" +
" \"residentKey\": \"required\",\n" +
" \"requireResidentKey\": true\n" +
" }}"
" }}",
preferImmediatelyAvailableCredentials = true,
)
val credentialData = request.credentialData
return RequestInfo.newCreateRequestInfo(
@@ -446,19 +448,28 @@ class CredentialManagerRepo(
}
private fun testGetRequestInfo(): RequestInfo {
val passwordOption = GetPasswordOption()
val passkeyOption = GetPublicKeyCredentialOption(
"json", preferImmediatelyAvailableCredentials = false)
return RequestInfo.newGetRequestInfo(
Binder(),
GetCredentialRequest.Builder(
Bundle()
).addCredentialOption(
CredentialOption(
"androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL",
Bundle(),
Bundle(), /*isSystemProviderRequired=*/
false
passwordOption.type,
passwordOption.requestData,
passwordOption.candidateQueryData,
passwordOption.isSystemProviderRequired
)
)
.build(),
).addCredentialOption(
CredentialOption(
passkeyOption.type,
passkeyOption.requestData,
passkeyOption.candidateQueryData,
passkeyOption.isSystemProviderRequired
)
).build(),
"com.google.android.youtube"
)
}

View File

@@ -50,7 +50,11 @@ import com.android.credentialmanager.getflow.RemoteEntryInfo
import androidx.credentials.CreateCredentialRequest
import androidx.credentials.CreateCustomCredentialRequest
import androidx.credentials.CreatePasswordRequest
import androidx.credentials.CredentialOption
import androidx.credentials.CreatePublicKeyCredentialRequest
import androidx.credentials.CreatePublicKeyCredentialRequestPrivileged
import androidx.credentials.GetPublicKeyCredentialOption
import androidx.credentials.GetPublicKeyCredentialOptionPrivileged
import androidx.credentials.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
import androidx.credentials.provider.Action
import androidx.credentials.provider.AuthenticationAction
@@ -172,10 +176,27 @@ class GetFlowUtils {
context: Context,
originName: String?,
): com.android.credentialmanager.getflow.RequestDisplayInfo? {
val getCredentialRequest = requestInfo.getCredentialRequest ?: return null
val preferImmediatelyAvailableCredentials = getCredentialRequest.credentialOptions.any {
val credentialOptionJetpack = CredentialOption.createFrom(
it.type,
it.credentialRetrievalData,
it.credentialRetrievalData,
it.isSystemProviderRequired
)
if (credentialOptionJetpack is GetPublicKeyCredentialOption) {
credentialOptionJetpack.preferImmediatelyAvailableCredentials
} else if (credentialOptionJetpack is GetPublicKeyCredentialOptionPrivileged) {
credentialOptionJetpack.preferImmediatelyAvailableCredentials
} else {
false
}
}
return com.android.credentialmanager.getflow.RequestDisplayInfo(
appName = originName
?: getAppLabel(context.packageManager, requestInfo.appPackageName)
?: return null
?: return null,
preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials
)
}
@@ -415,24 +436,25 @@ class CreateFlowUtils {
createCredentialRequestJetpack.password,
CredentialType.PASSWORD,
appLabel,
context.getDrawable(R.drawable.ic_password)!!
context.getDrawable(R.drawable.ic_password) ?: return null,
preferImmediatelyAvailableCredentials = false,
)
is CreatePublicKeyCredentialRequest -> {
val requestJson = createCredentialRequestJetpack.requestJson
val json = JSONObject(requestJson)
var name = ""
var displayName = ""
if (json.has("user")) {
val user: JSONObject = json.getJSONObject("user")
name = user.getString("name")
displayName = user.getString("displayName")
}
RequestDisplayInfo(
name,
displayName,
CredentialType.PASSKEY,
appLabel,
context.getDrawable(R.drawable.ic_passkey)!!
newRequestDisplayInfoFromPasskeyJson(
requestJson = createCredentialRequestJetpack.requestJson,
appLabel = appLabel,
context = context,
preferImmediatelyAvailableCredentials =
createCredentialRequestJetpack.preferImmediatelyAvailableCredentials,
)
}
is CreatePublicKeyCredentialRequestPrivileged -> {
newRequestDisplayInfoFromPasskeyJson(
requestJson = createCredentialRequestJetpack.requestJson,
appLabel = appLabel,
context = context,
preferImmediatelyAvailableCredentials =
createCredentialRequestJetpack.preferImmediatelyAvailableCredentials,
)
}
is CreateCustomCredentialRequest -> {
@@ -446,7 +468,8 @@ class CreateFlowUtils {
type = CredentialType.UNKNOWN,
appName = appLabel,
typeIcon = displayInfo.credentialTypeIcon?.loadDrawable(context)
?: context.getDrawable(R.drawable.ic_other_sign_in)!!
?: context.getDrawable(R.drawable.ic_other_sign_in) ?: return null,
preferImmediatelyAvailableCredentials = false,
)
}
else -> null
@@ -613,5 +636,29 @@ class CreateFlowUtils {
)
} else null
}
private fun newRequestDisplayInfoFromPasskeyJson(
requestJson: String,
appLabel: String,
context: Context,
preferImmediatelyAvailableCredentials: Boolean,
): RequestDisplayInfo? {
val json = JSONObject(requestJson)
var name = ""
var displayName = ""
if (json.has("user")) {
val user: JSONObject = json.getJSONObject("user")
name = user.getString("name")
displayName = user.getString("displayName")
}
return RequestDisplayInfo(
name,
displayName,
CredentialType.PASSKEY,
appLabel,
context.getDrawable(R.drawable.ic_passkey) ?: return null,
preferImmediatelyAvailableCredentials,
)
}
}
}

View File

@@ -38,7 +38,9 @@ data class CreateCredentialUiState(
)
internal fun hasContentToDisplay(state: CreateCredentialUiState): Boolean {
return state.sortedCreateOptionsPairs.isNotEmpty()
return state.sortedCreateOptionsPairs.isNotEmpty() ||
(!state.requestDisplayInfo.preferImmediatelyAvailableCredentials &&
state.remoteEntry != null)
}
open class ProviderInfo(
@@ -104,6 +106,7 @@ data class RequestDisplayInfo(
val type: CredentialType,
val appName: String,
val typeIcon: Drawable,
val preferImmediatelyAvailableCredentials: Boolean,
)
/**

View File

@@ -37,7 +37,8 @@ data class GetCredentialUiState(
internal fun hasContentToDisplay(state: GetCredentialUiState): Boolean {
return state.providerDisplayInfo.sortedUserNameToCredentialEntryList.isNotEmpty() ||
state.providerDisplayInfo.authenticationEntryList.isNotEmpty() ||
state.providerDisplayInfo.remoteEntry != null
(state.providerDisplayInfo.remoteEntry != null &&
!state.requestDisplayInfo.preferImmediatelyAvailableCredentials)
}
data class ProviderInfo(
@@ -146,6 +147,7 @@ class ActionEntryInfo(
data class RequestDisplayInfo(
val appName: String,
val preferImmediatelyAvailableCredentials: Boolean,
)
/**
@@ -246,7 +248,6 @@ private fun toActiveEntry(
private fun toGetScreenState(
providerDisplayInfo: ProviderDisplayInfo
): GetScreenState {
return if (providerDisplayInfo.sortedUserNameToCredentialEntryList.isEmpty() &&
providerDisplayInfo.remoteEntry == null &&
providerDisplayInfo.authenticationEntryList.all { it.isUnlockedAndEmpty })