Merge "[CredManUI] Honor preferImmediatelyAvailableCred" into udc-dev
This commit is contained in:
@@ -45,6 +45,8 @@ import com.android.credentialmanager.getflow.GetCredentialUiState
|
|||||||
import androidx.credentials.CreateCredentialRequest.DisplayInfo
|
import androidx.credentials.CreateCredentialRequest.DisplayInfo
|
||||||
import androidx.credentials.CreatePublicKeyCredentialRequest
|
import androidx.credentials.CreatePublicKeyCredentialRequest
|
||||||
import androidx.credentials.CreatePasswordRequest
|
import androidx.credentials.CreatePasswordRequest
|
||||||
|
import androidx.credentials.GetPasswordOption
|
||||||
|
import androidx.credentials.GetPublicKeyCredentialOption
|
||||||
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
@@ -71,7 +73,7 @@ class CredentialManagerRepo(
|
|||||||
requestInfo = intent.extras?.getParcelable(
|
requestInfo = intent.extras?.getParcelable(
|
||||||
RequestInfo.EXTRA_REQUEST_INFO,
|
RequestInfo.EXTRA_REQUEST_INFO,
|
||||||
RequestInfo::class.java
|
RequestInfo::class.java
|
||||||
) ?: testCreatePasswordRequestInfo()
|
) ?: testCreatePasskeyRequestInfo()
|
||||||
|
|
||||||
val originName: String? = when (requestInfo.type) {
|
val originName: String? = when (requestInfo.type) {
|
||||||
RequestInfo.TYPE_CREATE -> requestInfo.createCredentialRequest?.origin
|
RequestInfo.TYPE_CREATE -> requestInfo.createCredentialRequest?.origin
|
||||||
@@ -120,8 +122,7 @@ class CredentialManagerRepo(
|
|||||||
providerDisableListUiState,
|
providerDisableListUiState,
|
||||||
defaultProviderId,
|
defaultProviderId,
|
||||||
requestDisplayInfoUiState,
|
requestDisplayInfoUiState,
|
||||||
/** isOnPasskeyIntroStateAlready */
|
isOnPasskeyIntroStateAlready = false,
|
||||||
false,
|
|
||||||
isPasskeyFirstUse
|
isPasskeyFirstUse
|
||||||
)!!,
|
)!!,
|
||||||
getCredentialUiState = null,
|
getCredentialUiState = null,
|
||||||
@@ -400,7 +401,8 @@ class CredentialManagerRepo(
|
|||||||
" \"authenticatorSelection\": {\n" +
|
" \"authenticatorSelection\": {\n" +
|
||||||
" \"residentKey\": \"required\",\n" +
|
" \"residentKey\": \"required\",\n" +
|
||||||
" \"requireResidentKey\": true\n" +
|
" \"requireResidentKey\": true\n" +
|
||||||
" }}"
|
" }}",
|
||||||
|
preferImmediatelyAvailableCredentials = true,
|
||||||
)
|
)
|
||||||
val credentialData = request.credentialData
|
val credentialData = request.credentialData
|
||||||
return RequestInfo.newCreateRequestInfo(
|
return RequestInfo.newCreateRequestInfo(
|
||||||
@@ -446,19 +448,28 @@ class CredentialManagerRepo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun testGetRequestInfo(): RequestInfo {
|
private fun testGetRequestInfo(): RequestInfo {
|
||||||
|
val passwordOption = GetPasswordOption()
|
||||||
|
val passkeyOption = GetPublicKeyCredentialOption(
|
||||||
|
"json", preferImmediatelyAvailableCredentials = false)
|
||||||
return RequestInfo.newGetRequestInfo(
|
return RequestInfo.newGetRequestInfo(
|
||||||
Binder(),
|
Binder(),
|
||||||
GetCredentialRequest.Builder(
|
GetCredentialRequest.Builder(
|
||||||
Bundle()
|
Bundle()
|
||||||
).addCredentialOption(
|
).addCredentialOption(
|
||||||
CredentialOption(
|
CredentialOption(
|
||||||
"androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL",
|
passwordOption.type,
|
||||||
Bundle(),
|
passwordOption.requestData,
|
||||||
Bundle(), /*isSystemProviderRequired=*/
|
passwordOption.candidateQueryData,
|
||||||
false
|
passwordOption.isSystemProviderRequired
|
||||||
)
|
)
|
||||||
)
|
).addCredentialOption(
|
||||||
.build(),
|
CredentialOption(
|
||||||
|
passkeyOption.type,
|
||||||
|
passkeyOption.requestData,
|
||||||
|
passkeyOption.candidateQueryData,
|
||||||
|
passkeyOption.isSystemProviderRequired
|
||||||
|
)
|
||||||
|
).build(),
|
||||||
"com.google.android.youtube"
|
"com.google.android.youtube"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,11 @@ import com.android.credentialmanager.getflow.RemoteEntryInfo
|
|||||||
import androidx.credentials.CreateCredentialRequest
|
import androidx.credentials.CreateCredentialRequest
|
||||||
import androidx.credentials.CreateCustomCredentialRequest
|
import androidx.credentials.CreateCustomCredentialRequest
|
||||||
import androidx.credentials.CreatePasswordRequest
|
import androidx.credentials.CreatePasswordRequest
|
||||||
|
import androidx.credentials.CredentialOption
|
||||||
import androidx.credentials.CreatePublicKeyCredentialRequest
|
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.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
|
||||||
import androidx.credentials.provider.Action
|
import androidx.credentials.provider.Action
|
||||||
import androidx.credentials.provider.AuthenticationAction
|
import androidx.credentials.provider.AuthenticationAction
|
||||||
@@ -172,10 +176,27 @@ class GetFlowUtils {
|
|||||||
context: Context,
|
context: Context,
|
||||||
originName: String?,
|
originName: String?,
|
||||||
): com.android.credentialmanager.getflow.RequestDisplayInfo? {
|
): 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(
|
return com.android.credentialmanager.getflow.RequestDisplayInfo(
|
||||||
appName = originName
|
appName = originName
|
||||||
?: getAppLabel(context.packageManager, requestInfo.appPackageName)
|
?: getAppLabel(context.packageManager, requestInfo.appPackageName)
|
||||||
?: return null
|
?: return null,
|
||||||
|
preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,24 +436,25 @@ class CreateFlowUtils {
|
|||||||
createCredentialRequestJetpack.password,
|
createCredentialRequestJetpack.password,
|
||||||
CredentialType.PASSWORD,
|
CredentialType.PASSWORD,
|
||||||
appLabel,
|
appLabel,
|
||||||
context.getDrawable(R.drawable.ic_password)!!
|
context.getDrawable(R.drawable.ic_password) ?: return null,
|
||||||
|
preferImmediatelyAvailableCredentials = false,
|
||||||
)
|
)
|
||||||
is CreatePublicKeyCredentialRequest -> {
|
is CreatePublicKeyCredentialRequest -> {
|
||||||
val requestJson = createCredentialRequestJetpack.requestJson
|
newRequestDisplayInfoFromPasskeyJson(
|
||||||
val json = JSONObject(requestJson)
|
requestJson = createCredentialRequestJetpack.requestJson,
|
||||||
var name = ""
|
appLabel = appLabel,
|
||||||
var displayName = ""
|
context = context,
|
||||||
if (json.has("user")) {
|
preferImmediatelyAvailableCredentials =
|
||||||
val user: JSONObject = json.getJSONObject("user")
|
createCredentialRequestJetpack.preferImmediatelyAvailableCredentials,
|
||||||
name = user.getString("name")
|
)
|
||||||
displayName = user.getString("displayName")
|
}
|
||||||
}
|
is CreatePublicKeyCredentialRequestPrivileged -> {
|
||||||
RequestDisplayInfo(
|
newRequestDisplayInfoFromPasskeyJson(
|
||||||
name,
|
requestJson = createCredentialRequestJetpack.requestJson,
|
||||||
displayName,
|
appLabel = appLabel,
|
||||||
CredentialType.PASSKEY,
|
context = context,
|
||||||
appLabel,
|
preferImmediatelyAvailableCredentials =
|
||||||
context.getDrawable(R.drawable.ic_passkey)!!
|
createCredentialRequestJetpack.preferImmediatelyAvailableCredentials,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is CreateCustomCredentialRequest -> {
|
is CreateCustomCredentialRequest -> {
|
||||||
@@ -446,7 +468,8 @@ class CreateFlowUtils {
|
|||||||
type = CredentialType.UNKNOWN,
|
type = CredentialType.UNKNOWN,
|
||||||
appName = appLabel,
|
appName = appLabel,
|
||||||
typeIcon = displayInfo.credentialTypeIcon?.loadDrawable(context)
|
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
|
else -> null
|
||||||
@@ -613,5 +636,29 @@ class CreateFlowUtils {
|
|||||||
)
|
)
|
||||||
} else null
|
} 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,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,9 @@ data class CreateCredentialUiState(
|
|||||||
)
|
)
|
||||||
|
|
||||||
internal fun hasContentToDisplay(state: CreateCredentialUiState): Boolean {
|
internal fun hasContentToDisplay(state: CreateCredentialUiState): Boolean {
|
||||||
return state.sortedCreateOptionsPairs.isNotEmpty()
|
return state.sortedCreateOptionsPairs.isNotEmpty() ||
|
||||||
|
(!state.requestDisplayInfo.preferImmediatelyAvailableCredentials &&
|
||||||
|
state.remoteEntry != null)
|
||||||
}
|
}
|
||||||
|
|
||||||
open class ProviderInfo(
|
open class ProviderInfo(
|
||||||
@@ -104,6 +106,7 @@ data class RequestDisplayInfo(
|
|||||||
val type: CredentialType,
|
val type: CredentialType,
|
||||||
val appName: String,
|
val appName: String,
|
||||||
val typeIcon: Drawable,
|
val typeIcon: Drawable,
|
||||||
|
val preferImmediatelyAvailableCredentials: Boolean,
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ data class GetCredentialUiState(
|
|||||||
internal fun hasContentToDisplay(state: GetCredentialUiState): Boolean {
|
internal fun hasContentToDisplay(state: GetCredentialUiState): Boolean {
|
||||||
return state.providerDisplayInfo.sortedUserNameToCredentialEntryList.isNotEmpty() ||
|
return state.providerDisplayInfo.sortedUserNameToCredentialEntryList.isNotEmpty() ||
|
||||||
state.providerDisplayInfo.authenticationEntryList.isNotEmpty() ||
|
state.providerDisplayInfo.authenticationEntryList.isNotEmpty() ||
|
||||||
state.providerDisplayInfo.remoteEntry != null
|
(state.providerDisplayInfo.remoteEntry != null &&
|
||||||
|
!state.requestDisplayInfo.preferImmediatelyAvailableCredentials)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ProviderInfo(
|
data class ProviderInfo(
|
||||||
@@ -146,6 +147,7 @@ class ActionEntryInfo(
|
|||||||
|
|
||||||
data class RequestDisplayInfo(
|
data class RequestDisplayInfo(
|
||||||
val appName: String,
|
val appName: String,
|
||||||
|
val preferImmediatelyAvailableCredentials: Boolean,
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -246,7 +248,6 @@ private fun toActiveEntry(
|
|||||||
private fun toGetScreenState(
|
private fun toGetScreenState(
|
||||||
providerDisplayInfo: ProviderDisplayInfo
|
providerDisplayInfo: ProviderDisplayInfo
|
||||||
): GetScreenState {
|
): GetScreenState {
|
||||||
|
|
||||||
return if (providerDisplayInfo.sortedUserNameToCredentialEntryList.isEmpty() &&
|
return if (providerDisplayInfo.sortedUserNameToCredentialEntryList.isEmpty() &&
|
||||||
providerDisplayInfo.remoteEntry == null &&
|
providerDisplayInfo.remoteEntry == null &&
|
||||||
providerDisplayInfo.authenticationEntryList.all { it.isUnlockedAndEmpty })
|
providerDisplayInfo.authenticationEntryList.all { it.isUnlockedAndEmpty })
|
||||||
|
|||||||
Reference in New Issue
Block a user