Loading packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt +29 −268 Original line number Diff line number Diff line Loading @@ -18,14 +18,8 @@ package com.android.credentialmanager import android.content.Context import android.content.Intent import android.credentials.CreateCredentialRequest import android.credentials.Credential.TYPE_PASSWORD_CREDENTIAL import android.credentials.CredentialOption import android.credentials.GetCredentialRequest import android.credentials.ui.AuthenticationEntry import android.credentials.ui.CancelUiRequest import android.credentials.ui.Constants import android.credentials.ui.Entry import android.credentials.ui.CreateCredentialProviderData import android.credentials.ui.GetCredentialProviderData import android.credentials.ui.DisabledProviderData Loading @@ -35,23 +29,16 @@ import android.credentials.ui.BaseDialogResult import android.credentials.ui.ProviderPendingIntentResponse import android.credentials.ui.UserSelectionDialogResult import android.os.IBinder import android.os.Binder import android.os.Bundle import android.os.ResultReceiver import android.util.Log import com.android.credentialmanager.createflow.DisabledProviderInfo import com.android.credentialmanager.createflow.EnabledProviderInfo import com.android.credentialmanager.createflow.RequestDisplayInfo import com.android.credentialmanager.getflow.GetCredentialUiState import com.android.credentialmanager.getflow.findAutoSelectEntry import androidx.credentials.CreateCredentialRequest.DisplayInfo import androidx.credentials.CreatePublicKeyCredentialRequest import androidx.credentials.CreatePasswordRequest import androidx.credentials.GetPasswordOption import androidx.credentials.GetPublicKeyCredentialOption import com.android.credentialmanager.common.ProviderActivityState import java.time.Instant /** * Client for interacting with Credential Manager. Also holds data inputs from it. * Loading @@ -63,7 +50,7 @@ class CredentialManagerRepo( intent: Intent, userConfigRepo: UserConfigRepo, ) { val requestInfo: RequestInfo val requestInfo: RequestInfo? private val providerEnabledList: List<ProviderData> private val providerDisabledList: List<DisabledProviderData>? // TODO: require non-null. Loading @@ -75,27 +62,30 @@ class CredentialManagerRepo( requestInfo = intent.extras?.getParcelable( RequestInfo.EXTRA_REQUEST_INFO, RequestInfo::class.java ) ?: testGetRequestInfo() ) val originName: String? = when (requestInfo.type) { RequestInfo.TYPE_CREATE -> requestInfo.createCredentialRequest?.origin RequestInfo.TYPE_GET -> requestInfo.getCredentialRequest?.origin val originName: String? = when (requestInfo?.type) { RequestInfo.TYPE_CREATE -> requestInfo?.createCredentialRequest?.origin RequestInfo.TYPE_GET -> requestInfo?.getCredentialRequest?.origin else -> null } providerEnabledList = when (requestInfo.type) { providerEnabledList = when (requestInfo?.type) { RequestInfo.TYPE_CREATE -> intent.extras?.getParcelableArrayList( ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST, CreateCredentialProviderData::class.java ) ?: testCreateCredentialEnabledProviderList() ) ?: emptyList() RequestInfo.TYPE_GET -> intent.extras?.getParcelableArrayList( ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST, GetCredentialProviderData::class.java ) ?: testGetCredentialProviderList() ) ?: emptyList() else -> { throw IllegalStateException("Unrecognized request type: ${requestInfo.type}") Log.d( com.android.credentialmanager.common.Constants.LOG_TAG, "Unrecognized request type: ${requestInfo?.type}") emptyList() } } Loading @@ -103,7 +93,7 @@ class CredentialManagerRepo( intent.extras?.getParcelableArrayList( ProviderData.EXTRA_DISABLED_PROVIDER_DATA_LIST, DisabledProviderData::class.java ) ?: testDisabledProviderList() ) resultReceiver = intent.getParcelableExtra( Constants.EXTRA_RESULT_RECEIVER, Loading @@ -115,7 +105,7 @@ class CredentialManagerRepo( CancelUiRequestState(getAppLabel(context.getPackageManager(), it.appPackageName)) } initialUiState = when (requestInfo.type) { initialUiState = when (requestInfo?.type) { RequestInfo.TYPE_CREATE -> { val defaultProviderId = userConfigRepo.getDefaultProviderId() val isPasskeyFirstUse = userConfigRepo.getIsPasskeyFirstUse() Loading Loading @@ -151,7 +141,17 @@ class CredentialManagerRepo( cancelRequestState = cancelUiRequestState ) } else -> throw IllegalStateException("Unrecognized request type: ${requestInfo.type}") else -> { if (cancellationRequest != null) { UiState( createCredentialUiState = null, getCredentialUiState = null, cancelRequestState = cancelUiRequestState, ) } else { throw IllegalStateException("Unrecognized request type: ${requestInfo?.type}") } } } } Loading @@ -174,7 +174,7 @@ class CredentialManagerRepo( } fun onCancel(cancelCode: Int) { sendCancellationCode(cancelCode, requestInfo.token, resultReceiver) sendCancellationCode(cancelCode, requestInfo?.token, resultReceiver) } fun onOptionSelected( Loading @@ -185,7 +185,7 @@ class CredentialManagerRepo( resultData: Intent? = null, ) { val userSelectionDialogResult = UserSelectionDialogResult( requestInfo.token, requestInfo?.token, providerId, entryKey, entrySubkey, Loading Loading @@ -213,10 +213,9 @@ class CredentialManagerRepo( // IMPORTANT: new invocation should be mindful that this method can throw. private fun getCreateProviderEnableListInitialUiState(): List<EnabledProviderInfo> { val providerEnabledList = CreateFlowUtils.toEnabledProviderList( return CreateFlowUtils.toEnabledProviderList( providerEnabledList as List<CreateCredentialProviderData>, context ) return providerEnabledList } private fun getCreateProviderDisableListInitialUiState(): List<DisabledProviderInfo> { Loading Loading @@ -253,242 +252,4 @@ class CredentialManagerRepo( ) } } // TODO: below are prototype functionalities. To be removed for productionization. private fun testCreateCredentialEnabledProviderList(): List<CreateCredentialProviderData> { return listOf( CreateCredentialProviderData .Builder("io.enpass.app") .setSaveEntries( listOf<Entry>( CreateTestUtils.newCreateEntry( context, "key1", "subkey-1", "elisa.beckett@gmail.com", 20, 7, 27, Instant.ofEpochSecond(10L), "You can use your passkey on this or other devices. It is saved to " + "the Password Manager for elisa.beckett@gmail.com." ), CreateTestUtils.newCreateEntry( context, "key1", "subkey-2", "elisa.work@google.com", 20, 7, 27, Instant.ofEpochSecond(12L), null ), ) ).setRemoteEntry( CreateTestUtils.newRemoteCreateEntry(context, "key2", "subkey-1") ).build(), CreateCredentialProviderData .Builder("com.dashlane") .setSaveEntries( listOf<Entry>( CreateTestUtils.newCreateEntry( context, "key1", "subkey-3", "elisa.beckett@dashlane.com", 20, 7, 27, Instant.ofEpochSecond(11L), null ), CreateTestUtils.newCreateEntry( context, "key1", "subkey-4", "elisa.work@dashlane.com", 20, 7, 27, Instant.ofEpochSecond(14L), "You can use your passkey on this or other devices. It is saved to " + "the Password Manager for elisa.work@dashlane.com" ), ) ).build(), ) } private fun testDisabledProviderList(): List<DisabledProviderData>? { return listOf( DisabledProviderData("com.lastpass.lpandroid"), DisabledProviderData("com.google.android.youtube") ) } private fun testGetCredentialProviderList(): List<GetCredentialProviderData> { return listOf( GetCredentialProviderData.Builder("io.enpass.app") .setCredentialEntries( listOf( GetTestUtils.newPasswordEntry( context, "key1", "subkey-1", "elisa.family@outlook.com", null, Instant.ofEpochSecond(8000L) ), GetTestUtils.newPasskeyEntry( context, "key1", "subkey-1", "elisa.bakery@gmail.com", "Elisa Beckett", null ), GetTestUtils.newPasswordEntry( context, "key1", "subkey-2", "elisa.bakery@gmail.com", null, Instant.ofEpochSecond(10000L) ), GetTestUtils.newPasskeyEntry( context, "key1", "subkey-3", "elisa.family@outlook.com", "Elisa Beckett", Instant.ofEpochSecond(500L) ), ) ).setAuthenticationEntries( listOf( GetTestUtils.newAuthenticationEntry( context, "key2", "subkey-1", "locked-user1@gmail.com", AuthenticationEntry.STATUS_LOCKED ), GetTestUtils.newAuthenticationEntry( context, "key2", "subkey-2", "locked-user2@gmail.com", AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_MOST_RECENT ), ) ).setActionChips( listOf( GetTestUtils.newActionEntry( context, "key3", "subkey-1", "Open Google Password Manager", "elisa.beckett@gmail.com" ), GetTestUtils.newActionEntry( context, "key3", "subkey-2", "Open Google Password Manager", "beckett-family@gmail.com" ), ) ).setRemoteEntry( GetTestUtils.newRemoteCredentialEntry(context, "key4", "subkey-1") ).build(), GetCredentialProviderData.Builder("com.dashlane") .setCredentialEntries( listOf<Entry>( GetTestUtils.newPasswordEntry( context, "key1", "subkey-2", "elisa.family@outlook.com", null, Instant.ofEpochSecond(9000L) ), GetTestUtils.newPasswordEntry( context, "key1", "subkey-3", "elisa.work@outlook.com", null, Instant.ofEpochSecond(11000L) ), ) ).setAuthenticationEntries( listOf( GetTestUtils.newAuthenticationEntry( context, "key2", "subkey-1", "foo@email.com", AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_LESS_RECENT, ) ) ).setActionChips( listOf( GetTestUtils.newActionEntry( context, "key3", "subkey-1", "Open Enpass", "Manage passwords" ), ) ).build(), ) } private fun testCreatePasskeyRequestInfo(): RequestInfo { val request = CreatePublicKeyCredentialRequest( "{\"extensions\": {\n" + " \"webauthn.loc\": true\n" + " },\n" + " \"attestation\": \"direct\",\n" + " \"challenge\":" + " \"-rSQHXSQUdaK1N-La5bE-JPt6EVAW4SxX1K_tXhZ_Gk\",\n" + " \"user\": {\n" + " \"displayName\": \"testName\",\n" + " \"name\": \"credManTesting@gmail.com\",\n" + " \"id\": \"eD4o2KoXLpgegAtnM5cDhhUPvvk2\"\n" + " },\n" + " \"excludeCredentials\": [],\n" + " \"rp\": {\n" + " \"name\": \"Address Book\",\n" + " \"id\": \"addressbook-c7876.uc.r.appspot.com\"\n" + " },\n" + " \"timeout\": 60000,\n" + " \"pubKeyCredParams\": [\n" + " {\n" + " \"type\": \"public-key\",\n" + " \"alg\": -7\n" + " },\n" + " {\n" + " \"type\": \"public-key\",\n" + " \"alg\": -257\n" + " },\n" + " {\n" + " \"type\": \"public-key\",\n" + " \"alg\": -37\n" + " }\n" + " ],\n" + " \"authenticatorSelection\": {\n" + " \"residentKey\": \"required\",\n" + " \"requireResidentKey\": true\n" + " }}", preferImmediatelyAvailableCredentials = true, ) val credentialData = request.credentialData return RequestInfo.newCreateRequestInfo( Binder(), CreateCredentialRequest.Builder("androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL", credentialData, Bundle()) .setIsSystemProviderRequired(false) .setAlwaysSendAppInfoToProvider(true) .build(), "com.google.android.youtube" ) } private fun testCreatePasswordRequestInfo(): RequestInfo { val request = CreatePasswordRequest("beckett-bakert@gmail.com", "password123") return RequestInfo.newCreateRequestInfo( Binder(), CreateCredentialRequest.Builder(TYPE_PASSWORD_CREDENTIAL, request.credentialData, request.candidateQueryData) .setIsSystemProviderRequired(false) .setAlwaysSendAppInfoToProvider(true) .build(), "com.google.android.youtube" ) } private fun testCreateOtherCredentialRequestInfo(): RequestInfo { val data = Bundle() val displayInfo = DisplayInfo("my-username00", "Joe") data.putBundle( "androidx.credentials.BUNDLE_KEY_REQUEST_DISPLAY_INFO", displayInfo.toBundle() ) return RequestInfo.newCreateRequestInfo( Binder(), CreateCredentialRequest.Builder("other-sign-ins", data, Bundle()) .setIsSystemProviderRequired(false) .setAlwaysSendAppInfoToProvider(true) .build(), "com.google.android.youtube" ) } private fun testGetRequestInfo(): RequestInfo { val passwordOption = GetPasswordOption() val passkeyOption = GetPublicKeyCredentialOption( "json", preferImmediatelyAvailableCredentials = false) return RequestInfo.newGetRequestInfo( Binder(), GetCredentialRequest.Builder( Bundle() ).addCredentialOption( CredentialOption.Builder( passwordOption.type, passwordOption.requestData, passwordOption.candidateQueryData, ).setIsSystemProviderRequired(passwordOption.isSystemProviderRequired) .build() ).addCredentialOption( CredentialOption.Builder( passkeyOption.type, passkeyOption.requestData, passkeyOption.candidateQueryData, ).setIsSystemProviderRequired(passkeyOption.isSystemProviderRequired) .build() ).build(), "com.google.android.youtube" ) } } packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt +1 −1 Original line number Diff line number Diff line Loading @@ -111,7 +111,7 @@ class CredentialSelectorActivity : ComponentActivity() { ?: return Triple(false, false, null) if (viewModel != null && !viewModel.shouldCancelCurrentUi(cancelUiRequest.token)) { // Cancellation was for a different request, don't cancel the current UI. return Triple(false, false, null) return Triple(true, false, null) } val shouldShowCancellationUi = cancelUiRequest.shouldShowCancellationUi() Log.d( Loading packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt +6 −6 Original line number Diff line number Diff line Loading @@ -69,7 +69,7 @@ class CredentialSelectorViewModel( init{ uiMetrics.logNormal(LifecycleEvent.CREDMAN_ACTIVITY_INIT, credManRepo.requestInfo.appPackageName) credManRepo.requestInfo?.appPackageName) } /**************************************************************************/ Loading Loading @@ -97,10 +97,10 @@ class CredentialSelectorViewModel( this.credManRepo = credManRepo uiState = credManRepo.initState() if (this.credManRepo.requestInfo.token != credManRepo.requestInfo.token) { if (this.credManRepo.requestInfo?.token != credManRepo.requestInfo?.token) { this.uiMetrics.resetInstanceId() this.uiMetrics.logNormal(LifecycleEvent.CREDMAN_ACTIVITY_NEW_REQUEST, credManRepo.requestInfo.appPackageName) credManRepo.requestInfo?.appPackageName) } } Loading Loading @@ -174,14 +174,14 @@ class CredentialSelectorViewModel( private fun onInternalError() { Log.w(Constants.LOG_TAG, "UI closed due to illegal internal state") this.uiMetrics.logNormal(LifecycleEvent.CREDMAN_ACTIVITY_INTERNAL_ERROR, credManRepo.requestInfo.appPackageName) credManRepo.requestInfo?.appPackageName) credManRepo.onParsingFailureCancel() uiState = uiState.copy(dialogState = DialogState.COMPLETE) } /** Return true if the current UI's request token matches the UI cancellation request token. */ fun shouldCancelCurrentUi(cancelRequestToken: IBinder): Boolean { return credManRepo.requestInfo.token.equals(cancelRequestToken) return credManRepo.requestInfo?.token?.equals(cancelRequestToken) ?: false } /**************************************************************************/ Loading Loading @@ -405,6 +405,6 @@ class CredentialSelectorViewModel( @Composable fun logUiEvent(uiEventEnum: UiEventEnum) { this.uiMetrics.log(uiEventEnum, credManRepo.requestInfo.appPackageName) this.uiMetrics.log(uiEventEnum, credManRepo.requestInfo?.appPackageName) } } No newline at end of file packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt +6 −3 Original line number Diff line number Diff line Loading @@ -188,11 +188,11 @@ class GetFlowUtils { } fun toRequestDisplayInfo( requestInfo: RequestInfo, requestInfo: RequestInfo?, context: Context, originName: String?, ): com.android.credentialmanager.getflow.RequestDisplayInfo? { val getCredentialRequest = requestInfo.getCredentialRequest ?: return null val getCredentialRequest = requestInfo?.getCredentialRequest ?: return null val preferImmediatelyAvailableCredentials = getCredentialRequest.credentialOptions.any { val credentialOptionJetpack = CredentialOption.createFrom( it.type, Loading Loading @@ -450,10 +450,13 @@ class CreateFlowUtils { } fun toRequestDisplayInfo( requestInfo: RequestInfo, requestInfo: RequestInfo?, context: Context, originName: String?, ): RequestDisplayInfo? { if (requestInfo == null) { return null } val appLabel = originName ?: getAppLabel(context.packageManager, requestInfo.appPackageName) ?: return null Loading packages/CredentialManager/src/com/android/credentialmanager/TestUtils.ktdeleted 100644 → 0 +0 −252 File deleted.Preview size limit exceeded, changes collapsed. Show changes Loading
packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt +29 −268 Original line number Diff line number Diff line Loading @@ -18,14 +18,8 @@ package com.android.credentialmanager import android.content.Context import android.content.Intent import android.credentials.CreateCredentialRequest import android.credentials.Credential.TYPE_PASSWORD_CREDENTIAL import android.credentials.CredentialOption import android.credentials.GetCredentialRequest import android.credentials.ui.AuthenticationEntry import android.credentials.ui.CancelUiRequest import android.credentials.ui.Constants import android.credentials.ui.Entry import android.credentials.ui.CreateCredentialProviderData import android.credentials.ui.GetCredentialProviderData import android.credentials.ui.DisabledProviderData Loading @@ -35,23 +29,16 @@ import android.credentials.ui.BaseDialogResult import android.credentials.ui.ProviderPendingIntentResponse import android.credentials.ui.UserSelectionDialogResult import android.os.IBinder import android.os.Binder import android.os.Bundle import android.os.ResultReceiver import android.util.Log import com.android.credentialmanager.createflow.DisabledProviderInfo import com.android.credentialmanager.createflow.EnabledProviderInfo import com.android.credentialmanager.createflow.RequestDisplayInfo import com.android.credentialmanager.getflow.GetCredentialUiState import com.android.credentialmanager.getflow.findAutoSelectEntry import androidx.credentials.CreateCredentialRequest.DisplayInfo import androidx.credentials.CreatePublicKeyCredentialRequest import androidx.credentials.CreatePasswordRequest import androidx.credentials.GetPasswordOption import androidx.credentials.GetPublicKeyCredentialOption import com.android.credentialmanager.common.ProviderActivityState import java.time.Instant /** * Client for interacting with Credential Manager. Also holds data inputs from it. * Loading @@ -63,7 +50,7 @@ class CredentialManagerRepo( intent: Intent, userConfigRepo: UserConfigRepo, ) { val requestInfo: RequestInfo val requestInfo: RequestInfo? private val providerEnabledList: List<ProviderData> private val providerDisabledList: List<DisabledProviderData>? // TODO: require non-null. Loading @@ -75,27 +62,30 @@ class CredentialManagerRepo( requestInfo = intent.extras?.getParcelable( RequestInfo.EXTRA_REQUEST_INFO, RequestInfo::class.java ) ?: testGetRequestInfo() ) val originName: String? = when (requestInfo.type) { RequestInfo.TYPE_CREATE -> requestInfo.createCredentialRequest?.origin RequestInfo.TYPE_GET -> requestInfo.getCredentialRequest?.origin val originName: String? = when (requestInfo?.type) { RequestInfo.TYPE_CREATE -> requestInfo?.createCredentialRequest?.origin RequestInfo.TYPE_GET -> requestInfo?.getCredentialRequest?.origin else -> null } providerEnabledList = when (requestInfo.type) { providerEnabledList = when (requestInfo?.type) { RequestInfo.TYPE_CREATE -> intent.extras?.getParcelableArrayList( ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST, CreateCredentialProviderData::class.java ) ?: testCreateCredentialEnabledProviderList() ) ?: emptyList() RequestInfo.TYPE_GET -> intent.extras?.getParcelableArrayList( ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST, GetCredentialProviderData::class.java ) ?: testGetCredentialProviderList() ) ?: emptyList() else -> { throw IllegalStateException("Unrecognized request type: ${requestInfo.type}") Log.d( com.android.credentialmanager.common.Constants.LOG_TAG, "Unrecognized request type: ${requestInfo?.type}") emptyList() } } Loading @@ -103,7 +93,7 @@ class CredentialManagerRepo( intent.extras?.getParcelableArrayList( ProviderData.EXTRA_DISABLED_PROVIDER_DATA_LIST, DisabledProviderData::class.java ) ?: testDisabledProviderList() ) resultReceiver = intent.getParcelableExtra( Constants.EXTRA_RESULT_RECEIVER, Loading @@ -115,7 +105,7 @@ class CredentialManagerRepo( CancelUiRequestState(getAppLabel(context.getPackageManager(), it.appPackageName)) } initialUiState = when (requestInfo.type) { initialUiState = when (requestInfo?.type) { RequestInfo.TYPE_CREATE -> { val defaultProviderId = userConfigRepo.getDefaultProviderId() val isPasskeyFirstUse = userConfigRepo.getIsPasskeyFirstUse() Loading Loading @@ -151,7 +141,17 @@ class CredentialManagerRepo( cancelRequestState = cancelUiRequestState ) } else -> throw IllegalStateException("Unrecognized request type: ${requestInfo.type}") else -> { if (cancellationRequest != null) { UiState( createCredentialUiState = null, getCredentialUiState = null, cancelRequestState = cancelUiRequestState, ) } else { throw IllegalStateException("Unrecognized request type: ${requestInfo?.type}") } } } } Loading @@ -174,7 +174,7 @@ class CredentialManagerRepo( } fun onCancel(cancelCode: Int) { sendCancellationCode(cancelCode, requestInfo.token, resultReceiver) sendCancellationCode(cancelCode, requestInfo?.token, resultReceiver) } fun onOptionSelected( Loading @@ -185,7 +185,7 @@ class CredentialManagerRepo( resultData: Intent? = null, ) { val userSelectionDialogResult = UserSelectionDialogResult( requestInfo.token, requestInfo?.token, providerId, entryKey, entrySubkey, Loading Loading @@ -213,10 +213,9 @@ class CredentialManagerRepo( // IMPORTANT: new invocation should be mindful that this method can throw. private fun getCreateProviderEnableListInitialUiState(): List<EnabledProviderInfo> { val providerEnabledList = CreateFlowUtils.toEnabledProviderList( return CreateFlowUtils.toEnabledProviderList( providerEnabledList as List<CreateCredentialProviderData>, context ) return providerEnabledList } private fun getCreateProviderDisableListInitialUiState(): List<DisabledProviderInfo> { Loading Loading @@ -253,242 +252,4 @@ class CredentialManagerRepo( ) } } // TODO: below are prototype functionalities. To be removed for productionization. private fun testCreateCredentialEnabledProviderList(): List<CreateCredentialProviderData> { return listOf( CreateCredentialProviderData .Builder("io.enpass.app") .setSaveEntries( listOf<Entry>( CreateTestUtils.newCreateEntry( context, "key1", "subkey-1", "elisa.beckett@gmail.com", 20, 7, 27, Instant.ofEpochSecond(10L), "You can use your passkey on this or other devices. It is saved to " + "the Password Manager for elisa.beckett@gmail.com." ), CreateTestUtils.newCreateEntry( context, "key1", "subkey-2", "elisa.work@google.com", 20, 7, 27, Instant.ofEpochSecond(12L), null ), ) ).setRemoteEntry( CreateTestUtils.newRemoteCreateEntry(context, "key2", "subkey-1") ).build(), CreateCredentialProviderData .Builder("com.dashlane") .setSaveEntries( listOf<Entry>( CreateTestUtils.newCreateEntry( context, "key1", "subkey-3", "elisa.beckett@dashlane.com", 20, 7, 27, Instant.ofEpochSecond(11L), null ), CreateTestUtils.newCreateEntry( context, "key1", "subkey-4", "elisa.work@dashlane.com", 20, 7, 27, Instant.ofEpochSecond(14L), "You can use your passkey on this or other devices. It is saved to " + "the Password Manager for elisa.work@dashlane.com" ), ) ).build(), ) } private fun testDisabledProviderList(): List<DisabledProviderData>? { return listOf( DisabledProviderData("com.lastpass.lpandroid"), DisabledProviderData("com.google.android.youtube") ) } private fun testGetCredentialProviderList(): List<GetCredentialProviderData> { return listOf( GetCredentialProviderData.Builder("io.enpass.app") .setCredentialEntries( listOf( GetTestUtils.newPasswordEntry( context, "key1", "subkey-1", "elisa.family@outlook.com", null, Instant.ofEpochSecond(8000L) ), GetTestUtils.newPasskeyEntry( context, "key1", "subkey-1", "elisa.bakery@gmail.com", "Elisa Beckett", null ), GetTestUtils.newPasswordEntry( context, "key1", "subkey-2", "elisa.bakery@gmail.com", null, Instant.ofEpochSecond(10000L) ), GetTestUtils.newPasskeyEntry( context, "key1", "subkey-3", "elisa.family@outlook.com", "Elisa Beckett", Instant.ofEpochSecond(500L) ), ) ).setAuthenticationEntries( listOf( GetTestUtils.newAuthenticationEntry( context, "key2", "subkey-1", "locked-user1@gmail.com", AuthenticationEntry.STATUS_LOCKED ), GetTestUtils.newAuthenticationEntry( context, "key2", "subkey-2", "locked-user2@gmail.com", AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_MOST_RECENT ), ) ).setActionChips( listOf( GetTestUtils.newActionEntry( context, "key3", "subkey-1", "Open Google Password Manager", "elisa.beckett@gmail.com" ), GetTestUtils.newActionEntry( context, "key3", "subkey-2", "Open Google Password Manager", "beckett-family@gmail.com" ), ) ).setRemoteEntry( GetTestUtils.newRemoteCredentialEntry(context, "key4", "subkey-1") ).build(), GetCredentialProviderData.Builder("com.dashlane") .setCredentialEntries( listOf<Entry>( GetTestUtils.newPasswordEntry( context, "key1", "subkey-2", "elisa.family@outlook.com", null, Instant.ofEpochSecond(9000L) ), GetTestUtils.newPasswordEntry( context, "key1", "subkey-3", "elisa.work@outlook.com", null, Instant.ofEpochSecond(11000L) ), ) ).setAuthenticationEntries( listOf( GetTestUtils.newAuthenticationEntry( context, "key2", "subkey-1", "foo@email.com", AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_LESS_RECENT, ) ) ).setActionChips( listOf( GetTestUtils.newActionEntry( context, "key3", "subkey-1", "Open Enpass", "Manage passwords" ), ) ).build(), ) } private fun testCreatePasskeyRequestInfo(): RequestInfo { val request = CreatePublicKeyCredentialRequest( "{\"extensions\": {\n" + " \"webauthn.loc\": true\n" + " },\n" + " \"attestation\": \"direct\",\n" + " \"challenge\":" + " \"-rSQHXSQUdaK1N-La5bE-JPt6EVAW4SxX1K_tXhZ_Gk\",\n" + " \"user\": {\n" + " \"displayName\": \"testName\",\n" + " \"name\": \"credManTesting@gmail.com\",\n" + " \"id\": \"eD4o2KoXLpgegAtnM5cDhhUPvvk2\"\n" + " },\n" + " \"excludeCredentials\": [],\n" + " \"rp\": {\n" + " \"name\": \"Address Book\",\n" + " \"id\": \"addressbook-c7876.uc.r.appspot.com\"\n" + " },\n" + " \"timeout\": 60000,\n" + " \"pubKeyCredParams\": [\n" + " {\n" + " \"type\": \"public-key\",\n" + " \"alg\": -7\n" + " },\n" + " {\n" + " \"type\": \"public-key\",\n" + " \"alg\": -257\n" + " },\n" + " {\n" + " \"type\": \"public-key\",\n" + " \"alg\": -37\n" + " }\n" + " ],\n" + " \"authenticatorSelection\": {\n" + " \"residentKey\": \"required\",\n" + " \"requireResidentKey\": true\n" + " }}", preferImmediatelyAvailableCredentials = true, ) val credentialData = request.credentialData return RequestInfo.newCreateRequestInfo( Binder(), CreateCredentialRequest.Builder("androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL", credentialData, Bundle()) .setIsSystemProviderRequired(false) .setAlwaysSendAppInfoToProvider(true) .build(), "com.google.android.youtube" ) } private fun testCreatePasswordRequestInfo(): RequestInfo { val request = CreatePasswordRequest("beckett-bakert@gmail.com", "password123") return RequestInfo.newCreateRequestInfo( Binder(), CreateCredentialRequest.Builder(TYPE_PASSWORD_CREDENTIAL, request.credentialData, request.candidateQueryData) .setIsSystemProviderRequired(false) .setAlwaysSendAppInfoToProvider(true) .build(), "com.google.android.youtube" ) } private fun testCreateOtherCredentialRequestInfo(): RequestInfo { val data = Bundle() val displayInfo = DisplayInfo("my-username00", "Joe") data.putBundle( "androidx.credentials.BUNDLE_KEY_REQUEST_DISPLAY_INFO", displayInfo.toBundle() ) return RequestInfo.newCreateRequestInfo( Binder(), CreateCredentialRequest.Builder("other-sign-ins", data, Bundle()) .setIsSystemProviderRequired(false) .setAlwaysSendAppInfoToProvider(true) .build(), "com.google.android.youtube" ) } private fun testGetRequestInfo(): RequestInfo { val passwordOption = GetPasswordOption() val passkeyOption = GetPublicKeyCredentialOption( "json", preferImmediatelyAvailableCredentials = false) return RequestInfo.newGetRequestInfo( Binder(), GetCredentialRequest.Builder( Bundle() ).addCredentialOption( CredentialOption.Builder( passwordOption.type, passwordOption.requestData, passwordOption.candidateQueryData, ).setIsSystemProviderRequired(passwordOption.isSystemProviderRequired) .build() ).addCredentialOption( CredentialOption.Builder( passkeyOption.type, passkeyOption.requestData, passkeyOption.candidateQueryData, ).setIsSystemProviderRequired(passkeyOption.isSystemProviderRequired) .build() ).build(), "com.google.android.youtube" ) } }
packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt +1 −1 Original line number Diff line number Diff line Loading @@ -111,7 +111,7 @@ class CredentialSelectorActivity : ComponentActivity() { ?: return Triple(false, false, null) if (viewModel != null && !viewModel.shouldCancelCurrentUi(cancelUiRequest.token)) { // Cancellation was for a different request, don't cancel the current UI. return Triple(false, false, null) return Triple(true, false, null) } val shouldShowCancellationUi = cancelUiRequest.shouldShowCancellationUi() Log.d( Loading
packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt +6 −6 Original line number Diff line number Diff line Loading @@ -69,7 +69,7 @@ class CredentialSelectorViewModel( init{ uiMetrics.logNormal(LifecycleEvent.CREDMAN_ACTIVITY_INIT, credManRepo.requestInfo.appPackageName) credManRepo.requestInfo?.appPackageName) } /**************************************************************************/ Loading Loading @@ -97,10 +97,10 @@ class CredentialSelectorViewModel( this.credManRepo = credManRepo uiState = credManRepo.initState() if (this.credManRepo.requestInfo.token != credManRepo.requestInfo.token) { if (this.credManRepo.requestInfo?.token != credManRepo.requestInfo?.token) { this.uiMetrics.resetInstanceId() this.uiMetrics.logNormal(LifecycleEvent.CREDMAN_ACTIVITY_NEW_REQUEST, credManRepo.requestInfo.appPackageName) credManRepo.requestInfo?.appPackageName) } } Loading Loading @@ -174,14 +174,14 @@ class CredentialSelectorViewModel( private fun onInternalError() { Log.w(Constants.LOG_TAG, "UI closed due to illegal internal state") this.uiMetrics.logNormal(LifecycleEvent.CREDMAN_ACTIVITY_INTERNAL_ERROR, credManRepo.requestInfo.appPackageName) credManRepo.requestInfo?.appPackageName) credManRepo.onParsingFailureCancel() uiState = uiState.copy(dialogState = DialogState.COMPLETE) } /** Return true if the current UI's request token matches the UI cancellation request token. */ fun shouldCancelCurrentUi(cancelRequestToken: IBinder): Boolean { return credManRepo.requestInfo.token.equals(cancelRequestToken) return credManRepo.requestInfo?.token?.equals(cancelRequestToken) ?: false } /**************************************************************************/ Loading Loading @@ -405,6 +405,6 @@ class CredentialSelectorViewModel( @Composable fun logUiEvent(uiEventEnum: UiEventEnum) { this.uiMetrics.log(uiEventEnum, credManRepo.requestInfo.appPackageName) this.uiMetrics.log(uiEventEnum, credManRepo.requestInfo?.appPackageName) } } No newline at end of file
packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt +6 −3 Original line number Diff line number Diff line Loading @@ -188,11 +188,11 @@ class GetFlowUtils { } fun toRequestDisplayInfo( requestInfo: RequestInfo, requestInfo: RequestInfo?, context: Context, originName: String?, ): com.android.credentialmanager.getflow.RequestDisplayInfo? { val getCredentialRequest = requestInfo.getCredentialRequest ?: return null val getCredentialRequest = requestInfo?.getCredentialRequest ?: return null val preferImmediatelyAvailableCredentials = getCredentialRequest.credentialOptions.any { val credentialOptionJetpack = CredentialOption.createFrom( it.type, Loading Loading @@ -450,10 +450,13 @@ class CreateFlowUtils { } fun toRequestDisplayInfo( requestInfo: RequestInfo, requestInfo: RequestInfo?, context: Context, originName: String?, ): RequestDisplayInfo? { if (requestInfo == null) { return null } val appLabel = originName ?: getAppLabel(context.packageManager, requestInfo.appPackageName) ?: return null Loading
packages/CredentialManager/src/com/android/credentialmanager/TestUtils.ktdeleted 100644 → 0 +0 −252 File deleted.Preview size limit exceeded, changes collapsed. Show changes