Loading packages/CredentialManager/AndroidManifest.xml +0 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ android:supportsRtl="true" android:theme="@style/Theme.CredentialSelector"> <!--TODO: make sure implementing singleTop on NewIntent--> <activity android:name=".CredentialSelectorActivity" android:exported="true" Loading packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt +17 −12 Original line number Diff line number Diff line Loading @@ -49,7 +49,12 @@ import androidx.credentials.CreatePasswordRequest import java.time.Instant // Consider repo per screen, similar to view model? /** * Client for interacting with Credential Manager. Also holds data inputs from it. * * IMPORTANT: instantiation of the object can fail if the data inputs aren't valid. Callers need * to be equipped to handle this gracefully. */ class CredentialManagerRepo( private val context: Context, intent: Intent, Loading Loading @@ -81,7 +86,6 @@ class CredentialManagerRepo( GetCredentialProviderData::class.java ) ?: testGetCredentialProviderList() else -> { // TODO: fail gracefully throw IllegalStateException("Unrecognized request type: ${requestInfo.type}") } } Loading Loading @@ -167,9 +171,9 @@ class CredentialManagerRepo( ) } // IMPORTANT: new invocation should be mindful that this method can throw. private fun getCredentialInitialUiState(): GetCredentialUiState? { val providerEnabledList = GetFlowUtils.toProviderList( // TODO: handle runtime cast error providerEnabledList as List<GetCredentialProviderData>, context ) val requestDisplayInfo = GetFlowUtils.toRequestDisplayInfo(requestInfo, context) Loading @@ -179,9 +183,9 @@ class CredentialManagerRepo( ) } // IMPORTANT: new invocation should be mindful that this method can throw. private fun getCreateProviderEnableListInitialUiState(): List<EnabledProviderInfo> { val providerEnabledList = CreateFlowUtils.toEnabledProviderList( // Handle runtime cast error providerEnabledList as List<CreateCredentialProviderData>, context ) return providerEnabledList Loading Loading @@ -266,7 +270,7 @@ class CredentialManagerRepo( return listOf( GetCredentialProviderData.Builder("io.enpass.app") .setCredentialEntries( listOf<Entry>( listOf( GetTestUtils.newPasswordEntry( context, "key1", "subkey-1", "elisa.family@outlook.com", null, Instant.ofEpochSecond(8000L) Loading @@ -285,8 +289,11 @@ class CredentialManagerRepo( ), ) ).setAuthenticationEntries( listOf<Entry>( GetTestUtils.newAuthenticationEntry(context, "key2", "subkey-1"), listOf( GetTestUtils.newAuthenticationEntry( context, "key2", "subkey-1", "locked-user1@gmail.com"), GetTestUtils.newAuthenticationEntry( context, "key2", "subkey-2", "locked-user2@gmail.com"), ) ).setActionChips( listOf( Loading Loading @@ -315,9 +322,8 @@ class CredentialManagerRepo( ), ) ).setAuthenticationEntries( listOf<Entry>( GetTestUtils.newAuthenticationEntry(context, "key2", "subkey-1"), ) listOf(GetTestUtils.newAuthenticationEntry( context, "key2", "subkey-1", "foo@email.com")) ).setActionChips( listOf( GetTestUtils.newActionEntry( Loading Loading @@ -388,7 +394,6 @@ class CredentialManagerRepo( CreateCredentialRequest( "androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL", credentialData, // TODO: populate with actual data /*candidateQueryData=*/ Bundle(), /*isSystemProviderRequired=*/ false ), Loading packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt +10 −3 Original line number Diff line number Diff line Loading @@ -92,13 +92,20 @@ class CredentialSelectorActivity : ComponentActivity() { handleDialogState(viewModel.uiState.dialogState) } if (viewModel.uiState.createCredentialUiState != null) { val createCredentialUiState = viewModel.uiState.createCredentialUiState val getCredentialUiState = viewModel.uiState.getCredentialUiState if (createCredentialUiState != null) { CreateCredentialScreen( viewModel = viewModel, createCredentialUiState = createCredentialUiState, providerActivityLauncher = launcher ) } else if (getCredentialUiState != null) { GetCredentialScreen( viewModel = viewModel, getCredentialUiState = getCredentialUiState, providerActivityLauncher = launcher ) } else if (viewModel.uiState.getCredentialUiState != null) { GetCredentialScreen(viewModel = viewModel, providerActivityLauncher = launcher) } else { Log.d(Constants.LOG_TAG, "UI wasn't able to render neither get nor create flow") reportInstantiationErrorAndFinishActivity(credManRepo) Loading packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt +2 −2 Original line number Diff line number Diff line Loading @@ -255,14 +255,14 @@ class CredentialSelectorViewModel( } fun createFlowOnEntrySelectedFromFirstUseScreen(activeEntry: ActiveEntry) { val providerId = activeEntry.activeProvider.id createFlowOnDefaultChanged(providerId) uiState = uiState.copy( createCredentialUiState = uiState.createCredentialUiState?.copy( currentScreenState = CreateScreenState.CREATION_OPTION_SELECTION, activeEntry = activeEntry ) ) val providerId = uiState.createCredentialUiState?.activeEntry?.activeProvider?.id createFlowOnDefaultChanged(providerId) } fun createFlowOnDisabledProvidersSelected() { Loading packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt +33 −10 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.credentialmanager import android.app.slice.Slice import android.app.slice.SliceItem import android.content.ComponentName import android.content.Context import android.content.pm.PackageManager Loading Loading @@ -176,7 +177,9 @@ class GetFlowUtils { } /* From service data structure to UI credential entry list representation. */ /** * Note: caller required handle empty list due to parsing error. */ private fun getCredentialOptionInfoList( providerId: String, credentialEntries: List<Entry>, Loading Loading @@ -255,6 +258,9 @@ class GetFlowUtils { } } /** * Note: caller required handle empty list due to parsing error. */ private fun getAuthenticationEntryList( providerId: String, providerDisplayName: String, Loading @@ -262,16 +268,24 @@ class GetFlowUtils { authEntryList: List<Entry>, ): List<AuthenticationEntryInfo> { val result: MutableList<AuthenticationEntryInfo> = mutableListOf() authEntryList.forEach { authEntryList.forEach { entry -> val structuredAuthEntry = AuthenticationAction.fromSlice(it.slice) ?: return@forEach AuthenticationAction.fromSlice(entry.slice) ?: return@forEach // TODO: replace with official jetpack code. val titleItem: SliceItem? = entry.slice.items.firstOrNull { it.hasHint( "androidx.credentials.provider.authenticationAction.SLICE_HINT_TITLE") } val title: String = titleItem?.text?.toString() ?: providerDisplayName result.add(AuthenticationEntryInfo( providerId = providerId, entryKey = it.key, entrySubkey = it.subkey, entryKey = entry.key, entrySubkey = entry.subkey, pendingIntent = structuredAuthEntry.pendingIntent, fillInIntent = it.frameworkExtrasIntent, title = providerDisplayName, fillInIntent = entry.frameworkExtrasIntent, title = title, icon = providerIcon, )) } Loading @@ -279,7 +293,6 @@ class GetFlowUtils { } private fun getRemoteEntry(providerId: String, remoteEntry: Entry?): RemoteEntryInfo? { // TODO: should also call fromSlice after getting the official jetpack code. if (remoteEntry == null) { return null } Loading @@ -294,6 +307,9 @@ class GetFlowUtils { ) } /** * Note: caller required handle empty list due to parsing error. */ private fun getActionEntryList( providerId: String, actionEntries: List<Entry>, Loading Loading @@ -321,7 +337,9 @@ class GetFlowUtils { class CreateFlowUtils { companion object { // Returns the list (potentially empty) of enabled provider. /** * Note: caller required handle empty list due to parsing error. */ fun toEnabledProviderList( providerDataList: List<CreateCredentialProviderData>, context: Context, Loading @@ -346,7 +364,9 @@ class CreateFlowUtils { return providerList } // Returns the list (potentially empty) of disabled provider. /** * Note: caller required handle empty list due to parsing error. */ fun toDisabledProviderList( providerDataList: List<DisabledProviderData>?, context: Context, Loading Loading @@ -532,6 +552,9 @@ class CreateFlowUtils { } else null } /** * Note: caller required handle empty list due to parsing error. */ private fun toCreationOptionInfoList( providerId: String, creationEntries: List<Entry>, Loading Loading
packages/CredentialManager/AndroidManifest.xml +0 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ android:supportsRtl="true" android:theme="@style/Theme.CredentialSelector"> <!--TODO: make sure implementing singleTop on NewIntent--> <activity android:name=".CredentialSelectorActivity" android:exported="true" Loading
packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt +17 −12 Original line number Diff line number Diff line Loading @@ -49,7 +49,12 @@ import androidx.credentials.CreatePasswordRequest import java.time.Instant // Consider repo per screen, similar to view model? /** * Client for interacting with Credential Manager. Also holds data inputs from it. * * IMPORTANT: instantiation of the object can fail if the data inputs aren't valid. Callers need * to be equipped to handle this gracefully. */ class CredentialManagerRepo( private val context: Context, intent: Intent, Loading Loading @@ -81,7 +86,6 @@ class CredentialManagerRepo( GetCredentialProviderData::class.java ) ?: testGetCredentialProviderList() else -> { // TODO: fail gracefully throw IllegalStateException("Unrecognized request type: ${requestInfo.type}") } } Loading Loading @@ -167,9 +171,9 @@ class CredentialManagerRepo( ) } // IMPORTANT: new invocation should be mindful that this method can throw. private fun getCredentialInitialUiState(): GetCredentialUiState? { val providerEnabledList = GetFlowUtils.toProviderList( // TODO: handle runtime cast error providerEnabledList as List<GetCredentialProviderData>, context ) val requestDisplayInfo = GetFlowUtils.toRequestDisplayInfo(requestInfo, context) Loading @@ -179,9 +183,9 @@ class CredentialManagerRepo( ) } // IMPORTANT: new invocation should be mindful that this method can throw. private fun getCreateProviderEnableListInitialUiState(): List<EnabledProviderInfo> { val providerEnabledList = CreateFlowUtils.toEnabledProviderList( // Handle runtime cast error providerEnabledList as List<CreateCredentialProviderData>, context ) return providerEnabledList Loading Loading @@ -266,7 +270,7 @@ class CredentialManagerRepo( return listOf( GetCredentialProviderData.Builder("io.enpass.app") .setCredentialEntries( listOf<Entry>( listOf( GetTestUtils.newPasswordEntry( context, "key1", "subkey-1", "elisa.family@outlook.com", null, Instant.ofEpochSecond(8000L) Loading @@ -285,8 +289,11 @@ class CredentialManagerRepo( ), ) ).setAuthenticationEntries( listOf<Entry>( GetTestUtils.newAuthenticationEntry(context, "key2", "subkey-1"), listOf( GetTestUtils.newAuthenticationEntry( context, "key2", "subkey-1", "locked-user1@gmail.com"), GetTestUtils.newAuthenticationEntry( context, "key2", "subkey-2", "locked-user2@gmail.com"), ) ).setActionChips( listOf( Loading Loading @@ -315,9 +322,8 @@ class CredentialManagerRepo( ), ) ).setAuthenticationEntries( listOf<Entry>( GetTestUtils.newAuthenticationEntry(context, "key2", "subkey-1"), ) listOf(GetTestUtils.newAuthenticationEntry( context, "key2", "subkey-1", "foo@email.com")) ).setActionChips( listOf( GetTestUtils.newActionEntry( Loading Loading @@ -388,7 +394,6 @@ class CredentialManagerRepo( CreateCredentialRequest( "androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL", credentialData, // TODO: populate with actual data /*candidateQueryData=*/ Bundle(), /*isSystemProviderRequired=*/ false ), Loading
packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt +10 −3 Original line number Diff line number Diff line Loading @@ -92,13 +92,20 @@ class CredentialSelectorActivity : ComponentActivity() { handleDialogState(viewModel.uiState.dialogState) } if (viewModel.uiState.createCredentialUiState != null) { val createCredentialUiState = viewModel.uiState.createCredentialUiState val getCredentialUiState = viewModel.uiState.getCredentialUiState if (createCredentialUiState != null) { CreateCredentialScreen( viewModel = viewModel, createCredentialUiState = createCredentialUiState, providerActivityLauncher = launcher ) } else if (getCredentialUiState != null) { GetCredentialScreen( viewModel = viewModel, getCredentialUiState = getCredentialUiState, providerActivityLauncher = launcher ) } else if (viewModel.uiState.getCredentialUiState != null) { GetCredentialScreen(viewModel = viewModel, providerActivityLauncher = launcher) } else { Log.d(Constants.LOG_TAG, "UI wasn't able to render neither get nor create flow") reportInstantiationErrorAndFinishActivity(credManRepo) Loading
packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt +2 −2 Original line number Diff line number Diff line Loading @@ -255,14 +255,14 @@ class CredentialSelectorViewModel( } fun createFlowOnEntrySelectedFromFirstUseScreen(activeEntry: ActiveEntry) { val providerId = activeEntry.activeProvider.id createFlowOnDefaultChanged(providerId) uiState = uiState.copy( createCredentialUiState = uiState.createCredentialUiState?.copy( currentScreenState = CreateScreenState.CREATION_OPTION_SELECTION, activeEntry = activeEntry ) ) val providerId = uiState.createCredentialUiState?.activeEntry?.activeProvider?.id createFlowOnDefaultChanged(providerId) } fun createFlowOnDisabledProvidersSelected() { Loading
packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt +33 −10 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.credentialmanager import android.app.slice.Slice import android.app.slice.SliceItem import android.content.ComponentName import android.content.Context import android.content.pm.PackageManager Loading Loading @@ -176,7 +177,9 @@ class GetFlowUtils { } /* From service data structure to UI credential entry list representation. */ /** * Note: caller required handle empty list due to parsing error. */ private fun getCredentialOptionInfoList( providerId: String, credentialEntries: List<Entry>, Loading Loading @@ -255,6 +258,9 @@ class GetFlowUtils { } } /** * Note: caller required handle empty list due to parsing error. */ private fun getAuthenticationEntryList( providerId: String, providerDisplayName: String, Loading @@ -262,16 +268,24 @@ class GetFlowUtils { authEntryList: List<Entry>, ): List<AuthenticationEntryInfo> { val result: MutableList<AuthenticationEntryInfo> = mutableListOf() authEntryList.forEach { authEntryList.forEach { entry -> val structuredAuthEntry = AuthenticationAction.fromSlice(it.slice) ?: return@forEach AuthenticationAction.fromSlice(entry.slice) ?: return@forEach // TODO: replace with official jetpack code. val titleItem: SliceItem? = entry.slice.items.firstOrNull { it.hasHint( "androidx.credentials.provider.authenticationAction.SLICE_HINT_TITLE") } val title: String = titleItem?.text?.toString() ?: providerDisplayName result.add(AuthenticationEntryInfo( providerId = providerId, entryKey = it.key, entrySubkey = it.subkey, entryKey = entry.key, entrySubkey = entry.subkey, pendingIntent = structuredAuthEntry.pendingIntent, fillInIntent = it.frameworkExtrasIntent, title = providerDisplayName, fillInIntent = entry.frameworkExtrasIntent, title = title, icon = providerIcon, )) } Loading @@ -279,7 +293,6 @@ class GetFlowUtils { } private fun getRemoteEntry(providerId: String, remoteEntry: Entry?): RemoteEntryInfo? { // TODO: should also call fromSlice after getting the official jetpack code. if (remoteEntry == null) { return null } Loading @@ -294,6 +307,9 @@ class GetFlowUtils { ) } /** * Note: caller required handle empty list due to parsing error. */ private fun getActionEntryList( providerId: String, actionEntries: List<Entry>, Loading Loading @@ -321,7 +337,9 @@ class GetFlowUtils { class CreateFlowUtils { companion object { // Returns the list (potentially empty) of enabled provider. /** * Note: caller required handle empty list due to parsing error. */ fun toEnabledProviderList( providerDataList: List<CreateCredentialProviderData>, context: Context, Loading @@ -346,7 +364,9 @@ class CreateFlowUtils { return providerList } // Returns the list (potentially empty) of disabled provider. /** * Note: caller required handle empty list due to parsing error. */ fun toDisabledProviderList( providerDataList: List<DisabledProviderData>?, context: Context, Loading Loading @@ -532,6 +552,9 @@ class CreateFlowUtils { } else null } /** * Note: caller required handle empty list due to parsing error. */ private fun toCreationOptionInfoList( providerId: String, creationEntries: List<Entry>, Loading