Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7928b38c authored by Helen Qin's avatar Helen Qin Committed by Android (Google) Code Review
Browse files

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

parents d22e8c62 45dee42c
Loading
Loading
Loading
Loading
+21 −10
Original line number Diff line number Diff line
@@ -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
                )
            ).addCredentialOption(
                CredentialOption(
                    passkeyOption.type,
                    passkeyOption.requestData,
                    passkeyOption.candidateQueryData,
                    passkeyOption.isSystemProviderRequired
                )
                .build(),
            ).build(),
            "com.google.android.youtube"
        )
    }
+65 −18
Original line number Diff line number Diff line
@@ -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")
                    newRequestDisplayInfoFromPasskeyJson(
                        requestJson = createCredentialRequestJetpack.requestJson,
                        appLabel = appLabel,
                        context = context,
                        preferImmediatelyAvailableCredentials =
                        createCredentialRequestJetpack.preferImmediatelyAvailableCredentials,
                    )
                }
                    RequestDisplayInfo(
                        name,
                        displayName,
                        CredentialType.PASSKEY,
                        appLabel,
                        context.getDrawable(R.drawable.ic_passkey)!!
                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,
            )
        }
    }
}
+4 −1
Original line number Diff line number Diff line
@@ -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,
)

/**
+3 −2
Original line number Diff line number Diff line
@@ -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 })