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

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

Merge "Use service info instead of app info and revamped data parsing"

parents 3ec8a748 57c45eeb
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -56,14 +56,14 @@ public class BaseDialogResult implements Parcelable {
     * The intent extra key for the {@code BaseDialogResult} object when the credential
     * selector activity finishes.
     */
    private static final String EXTRA_BASE_RESULT =
            "android.credentials.ui.extra.BASE_RESULT";
    private static final String EXTRA_BASE_RESULT = "android.credentials.ui.extra.BASE_RESULT";

    /** @hide **/
    @IntDef(prefix = {"RESULT_CODE_"}, value = {
            RESULT_CODE_DIALOG_USER_CANCELED,
            RESULT_CODE_CANCELED_AND_LAUNCHED_SETTINGS,
            RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION,
            RESULT_CODE_DATA_PARSING_FAILURE,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ResultCode {}
@@ -80,6 +80,10 @@ public class BaseDialogResult implements Parcelable {
     * {@code resultData}.
     */
    public static final int RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION = 2;
    /**
     * The UI was canceled because it failed to parse the incoming data.
     */
    public static final int RESULT_CODE_DATA_PARSING_FAILURE = 3;

    @NonNull
    private final IBinder mRequestToken;
+409 −374
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ class CredentialManagerRepo(
    val requestInfo: RequestInfo
    private val providerEnabledList: List<ProviderData>
    private val providerDisabledList: List<DisabledProviderData>?

    // TODO: require non-null.
    val resultReceiver: ResultReceiver?

@@ -109,7 +110,11 @@ class CredentialManagerRepo(
        onCancel(BaseDialogResult.RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION)
    }

  private fun onCancel(cancelCode: Int) {
    fun onParsingFailureCancel() {
        onCancel(BaseDialogResult.RESULT_CODE_DATA_PARSING_FAILURE)
    }

    fun onCancel(cancelCode: Int) {
        val resultData = Bundle()
        BaseDialogResult.addToBundle(BaseDialogResult(requestInfo.token), resultData)
        resultReceiver?.send(cancelCode, resultData)
@@ -131,34 +136,40 @@ class CredentialManagerRepo(
        )
        val resultData = Bundle()
        UserSelectionDialogResult.addToBundle(userSelectionDialogResult, resultData)
    resultReceiver?.send(BaseDialogResult.RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION, resultData)
        resultReceiver?.send(
            BaseDialogResult.RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION,
            resultData
        )
    }

  fun getCredentialInitialUiState(): GetCredentialUiState {
    fun getCredentialInitialUiState(): GetCredentialUiState? {
        val providerEnabledList = GetFlowUtils.toProviderList(
            // TODO: handle runtime cast error
      providerEnabledList as List<GetCredentialProviderData>, context)
            providerEnabledList as List<GetCredentialProviderData>, context
        )
        val requestDisplayInfo = GetFlowUtils.toRequestDisplayInfo(requestInfo, context)
        return GetCredentialUiState(
            providerEnabledList,
      requestDisplayInfo,
            requestDisplayInfo ?: return null,
        )
    }

    fun getCreateProviderEnableListInitialUiState(): List<EnabledProviderInfo> {
        val providerEnabledList = CreateFlowUtils.toEnabledProviderList(
            // Handle runtime cast error
      providerEnabledList as List<CreateCredentialProviderData>, context)
            providerEnabledList as List<CreateCredentialProviderData>, context
        )
        return providerEnabledList
    }

  fun getCreateProviderDisableListInitialUiState(): List<DisabledProviderInfo>? {
    fun getCreateProviderDisableListInitialUiState(): List<DisabledProviderInfo> {
        return CreateFlowUtils.toDisabledProviderList(
            // Handle runtime cast error
      providerDisabledList, context)
            providerDisabledList, context
        )
    }

  fun getCreateRequestDisplayInfoInitialUiState(): RequestDisplayInfo {
    fun getCreateRequestDisplayInfoInitialUiState(): RequestDisplayInfo? {
        return CreateFlowUtils.toRequestDisplayInfo(requestInfo, context)
    }

@@ -169,12 +180,16 @@ class CredentialManagerRepo(
                .Builder("io.enpass.app")
                .setSaveEntries(
                    listOf<Entry>(
                      newCreateEntry("key1", "subkey-1", "elisa.beckett@gmail.com",
                        newCreateEntry(
                            "key1", "subkey-1", "elisa.beckett@gmail.com",
                            20, 7, 27, 10L,
                          "Optional footer description"),
                      newCreateEntry("key1", "subkey-2", "elisa.work@google.com",
                            "Optional footer description"
                        ),
                        newCreateEntry(
                            "key1", "subkey-2", "elisa.work@google.com",
                            20, 7, 27, 12L,
                      null),
                            null
                        ),
                    )
                )
                .setRemoteEntry(
@@ -185,12 +200,16 @@ class CredentialManagerRepo(
                .Builder("com.dashlane")
                .setSaveEntries(
                    listOf<Entry>(
                      newCreateEntry("key1", "subkey-3", "elisa.beckett@dashlane.com",
                        newCreateEntry(
                            "key1", "subkey-3", "elisa.beckett@dashlane.com",
                            20, 7, 27, 11L,
                          null),
                      newCreateEntry("key1", "subkey-4", "elisa.work@dashlane.com",
                            null
                        ),
                        newCreateEntry(
                            "key1", "subkey-4", "elisa.work@dashlane.com",
                            20, 7, 27, 14L,
                          null),
                            null
                        ),
                    )
                )
                .build(),
@@ -311,13 +330,17 @@ class CredentialManagerRepo(
            .setPackage("com.androidauth.androidvault")
        intent.putExtra("provider_extra_sample", "testprovider")

        val pendingIntent = PendingIntent.getActivity(context, 1,
        val pendingIntent = PendingIntent.getActivity(
            context, 1,
            intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
                or PendingIntent.FLAG_ONE_SHOT))
                or PendingIntent.FLAG_ONE_SHOT)
        )

        val credentialEntry = CredentialEntry(credentialType, credentialTypeDisplayName, userName,
        val credentialEntry = CredentialEntry(
            credentialType, credentialTypeDisplayName, userName,
            userDisplayName, pendingIntent, lastUsedTimeMillis
                ?: 0L, null, false)
                ?: 0L, null, false
        )

        return Entry(
            key,
@@ -340,18 +363,22 @@ class CredentialManagerRepo(
        val intent = Intent("com.androidauth.androidvault.CONFIRM_PASSWORD")
            .setPackage("com.androidauth.androidvault")
        intent.putExtra("provider_extra_sample", "testprovider")
        val pendingIntent = PendingIntent.getActivity(context, 1,
        val pendingIntent = PendingIntent.getActivity(
            context, 1,
            intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
                or PendingIntent.FLAG_ONE_SHOT))
                or PendingIntent.FLAG_ONE_SHOT)
        )
        val createPasswordRequest = android.service.credentials.CreateCredentialRequest(
            android.service.credentials.CallingAppInfo(
                        context.applicationInfo.packageName, SigningInfo()),
                context.applicationInfo.packageName, SigningInfo()
            ),
            TYPE_PASSWORD_CREDENTIAL,
            toCredentialDataBundle("beckett-bakert@gmail.com", "password123")
        )
        val fillInIntent = Intent().putExtra(
            CredentialProviderService.EXTRA_CREATE_CREDENTIAL_REQUEST,
                createPasswordRequest)
            createPasswordRequest
        )

        val createEntry = CreateEntry(
            providerDisplayName, pendingIntent,
@@ -359,7 +386,8 @@ class CredentialManagerRepo(
            listOf(
                CredentialCountInformation.createPasswordCountInformation(passwordCount),
                CredentialCountInformation.createPublicKeyCountInformation(passkeyCount),
                ), footerDescription)
            ), footerDescription
        )
        return Entry(
            key,
            subkey,
@@ -382,11 +410,13 @@ class CredentialManagerRepo(
    }

    private fun testCreatePasskeyRequestInfo(): RequestInfo {
    val request = CreatePublicKeyCredentialRequest("{\"extensions\": {\n" +
        val request = CreatePublicKeyCredentialRequest(
            "{\"extensions\": {\n" +
                "                     \"webauthn.loc\": true\n" +
                "                   },\n" +
                "                   \"attestation\": \"direct\",\n" +
            "                   \"challenge\": \"-rSQHXSQUdaK1N-La5bE-JPt6EVAW4SxX1K_tXhZ_Gk\",\n" +
                "                   \"challenge\":" +
                " \"-rSQHXSQUdaK1N-La5bE-JPt6EVAW4SxX1K_tXhZ_Gk\",\n" +
                "                   \"user\": {\n" +
                "                     \"displayName\": \"testName\",\n" +
                "                     \"name\": \"credManTesting@gmail.com\",\n" +
@@ -415,7 +445,8 @@ class CredentialManagerRepo(
                "                   \"authenticatorSelection\": {\n" +
                "                     \"residentKey\": \"required\",\n" +
                "                     \"requireResidentKey\": true\n" +
            "                   }}")
                "                   }}"
        )
        val credentialData = request.credentialData
        return RequestInfo.newCreateRequestInfo(
            Binder(),
@@ -467,7 +498,11 @@ class CredentialManagerRepo(
            )
                .addGetCredentialOption(
                    GetCredentialOption(
            TYPE_PUBLIC_KEY_CREDENTIAL, Bundle(), Bundle(), /*isSystemProviderRequired=*/ false)
                        TYPE_PUBLIC_KEY_CREDENTIAL,
                        Bundle(),
                        Bundle(), /*isSystemProviderRequired=*/
                        false
                    )
                )
                .build(),
            "com.google.android.youtube"
+47 −11
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.lifecycle.viewmodel.compose.viewModel
import com.android.credentialmanager.common.Constants
import com.android.credentialmanager.common.DialogState
import com.android.credentialmanager.common.ProviderActivityResult
import com.android.credentialmanager.createflow.CreateCredentialScreen
@@ -45,12 +46,16 @@ class CredentialSelectorActivity : ComponentActivity() {
        super.onCreate(savedInstanceState)
        val credManRepo = CredentialManagerRepo(this, intent)
        UserConfigRepo.setup(this)
        val requestInfo = credManRepo.requestInfo
        try {
            setContent {
                CredentialSelectorTheme {
                CredentialManagerBottomSheet(requestInfo.type, credManRepo)
                    CredentialManagerBottomSheet(credManRepo.requestInfo.type, credManRepo)
                }
            }
        } catch (e: Exception) {
            Log.e(Constants.LOG_TAG, "Failed to show the credential selector", e)
            reportInstantiationErrorAndFinishActivity(credManRepo)
        }
    }

    @ExperimentalMaterialApi
@@ -65,7 +70,22 @@ class CredentialSelectorActivity : ComponentActivity() {
        when (requestType) {
            RequestInfo.TYPE_CREATE -> {
                val viewModel: CreateCredentialViewModel = viewModel {
                    CreateCredentialViewModel(credManRepo)
                    val vm = CreateCredentialViewModel.newInstance(
                        credManRepo = credManRepo,
                        providerEnableListUiState =
                        credManRepo.getCreateProviderEnableListInitialUiState(),
                        providerDisableListUiState =
                        credManRepo.getCreateProviderDisableListInitialUiState(),
                        requestDisplayInfoUiState =
                        credManRepo.getCreateRequestDisplayInfoInitialUiState()
                    )
                    if (vm == null) {
                        // Input parsing failed. Close the activity.
                        reportInstantiationErrorAndFinishActivity(credManRepo)
                        throw IllegalStateException()
                    } else {
                        vm
                    }
                }
                LaunchedEffect(viewModel.uiState.dialogState) {
                    handleDialogState(viewModel.uiState.dialogState)
@@ -74,11 +94,21 @@ class CredentialSelectorActivity : ComponentActivity() {
                    viewModel.onProviderActivityResult(it)
                    providerActivityResult.value = null
                }
                CreateCredentialScreen(viewModel = viewModel, providerActivityLauncher = launcher)
                CreateCredentialScreen(
                    viewModel = viewModel,
                    providerActivityLauncher = launcher
                )
            }
            RequestInfo.TYPE_GET -> {
                val viewModel: GetCredentialViewModel = viewModel {
                    GetCredentialViewModel(credManRepo)
                    val initialUiState = credManRepo.getCredentialInitialUiState()
                    if (initialUiState == null) {
                        // Input parsing failed. Close the activity.
                        reportInstantiationErrorAndFinishActivity(credManRepo)
                        throw IllegalStateException()
                    } else {
                        GetCredentialViewModel(credManRepo, initialUiState)
                    }
                }
                LaunchedEffect(viewModel.uiState.dialogState) {
                    handleDialogState(viewModel.uiState.dialogState)
@@ -90,18 +120,24 @@ class CredentialSelectorActivity : ComponentActivity() {
                GetCredentialScreen(viewModel = viewModel, providerActivityLauncher = launcher)
            }
            else -> {
                Log.w("AccountSelector", "Unknown type, not rendering any UI")
                this.finish()
                Log.d(Constants.LOG_TAG, "Unknown type, not rendering any UI")
                reportInstantiationErrorAndFinishActivity(credManRepo)
            }
        }
    }

    private fun reportInstantiationErrorAndFinishActivity(credManRepo: CredentialManagerRepo) {
        Log.w(Constants.LOG_TAG, "Finishing the activity due to instantiation failure.")
        credManRepo.onParsingFailureCancel()
        this@CredentialSelectorActivity.finish()
    }

    private fun handleDialogState(dialogState: DialogState) {
        if (dialogState == DialogState.COMPLETE) {
            Log.i("AccountSelector", "Received signal to finish the activity.")
            Log.d(Constants.LOG_TAG, "Received signal to finish the activity.")
            this@CredentialSelectorActivity.finish()
        } else if (dialogState == DialogState.CANCELED_FOR_SETTINGS) {
            Log.i("AccountSelector", "Received signal to finish the activity and launch settings.")
            Log.d(Constants.LOG_TAG, "Received signal to finish the activity and launch settings.")
            this@CredentialSelectorActivity.startActivity(Intent(Settings.ACTION_SYNC_SETTINGS))
            this@CredentialSelectorActivity.finish()
        }
+411 −345

File changed.

Preview size limit exceeded, changes collapsed.

+23 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.credentialmanager.common

class Constants {
    companion object Constants {
        const val LOG_TAG = "CredentialSelector"
    }
}
 No newline at end of file
Loading