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

Commit 7be165fb authored by Daniel Kim's avatar Daniel Kim Committed by Android (Google) Code Review
Browse files

Merge "Associate autofillId with credential request and response" into main

parents f9a6b1a7 da63e412
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -53,6 +53,15 @@ public final class GetCandidateCredentialsResponse implements Parcelable {
        mCandidateProviderDataList = new ArrayList<>(candidateProviderDataList);
    }

    /**
     * Returns candidate provider data list.
     *
     * @hide
     */
    public List<GetCredentialProviderData> getCandidateProviderDataList() {
        return mCandidateProviderDataList;
    }

    protected GetCandidateCredentialsResponse(Parcel in) {
        List<GetCredentialProviderData> candidateProviderDataList = new ArrayList<>();
        in.readTypedList(candidateProviderDataList, GetCredentialProviderData.CREATOR);
+12 −0
Original line number Diff line number Diff line
@@ -153,6 +153,18 @@ public abstract class CredentialProviderService extends Service {
    public static final String EXTRA_BEGIN_GET_CREDENTIAL_REQUEST =
            "android.service.credentials.extra.BEGIN_GET_CREDENTIAL_REQUEST";

    /**
     * The key to autofillId associated with the requested credential option and the corresponding
     * credential entry. The associated autofillId will be contained inside the candidate query
     * bundle of {@link android.credentials.CredentialOption} if requested through the
     * {@link com.android.credentialmanager.autofill.CredentialAutofillService}. The resulting
     * credential entry will  contain the autofillId inside its framework extras intent.
     *
     * @hide
     */
    public static final String EXTRA_AUTOFILL_ID =
            "android.service.credentials.extra.AUTOFILL_ID";

    private static final String TAG = "CredProviderService";

     /**
+29 −18
Original line number Diff line number Diff line
@@ -18,21 +18,23 @@ package com.android.credentialmanager.autofill

import android.app.assist.AssistStructure
import android.content.Context
import android.credentials.GetCredentialRequest
import android.credentials.CredentialManager
import android.credentials.GetCandidateCredentialsResponse
import android.credentials.CredentialOption
import android.credentials.GetCandidateCredentialsException
import android.credentials.GetCandidateCredentialsResponse
import android.credentials.GetCredentialRequest
import android.os.Bundle
import android.os.CancellationSignal
import android.os.OutcomeReceiver
import android.service.autofill.FillRequest
import android.service.autofill.AutofillService
import android.service.autofill.FillResponse
import android.service.autofill.FillCallback
import android.service.autofill.SaveRequest
import android.service.autofill.FillRequest
import android.service.autofill.FillResponse
import android.service.autofill.SaveCallback
import android.service.autofill.SaveRequest
import android.service.credentials.CredentialProviderService
import android.util.Log
import android.view.autofill.AutofillId
import org.json.JSONObject
import java.util.concurrent.Executors

@@ -129,27 +131,31 @@ class CredentialAutofillService : AutofillService() {
    }

    private fun traverseNode(
            viewNode: AssistStructure.ViewNode?,
            viewNode: AssistStructure.ViewNode,
            cmRequests: MutableList<CredentialOption>
    ) {
        val options = getCredentialOptionsFromViewNode(viewNode)
        viewNode.autofillId?.let {
            val options = getCredentialOptionsFromViewNode(viewNode, it)
            cmRequests.addAll(options)
        }

        val children: List<AssistStructure.ViewNode>? =
                viewNode?.run {
        val children: List<AssistStructure.ViewNode> =
                viewNode.run {
                    (0 until childCount).map { getChildAt(it) }
                }

        children?.forEach { childNode: AssistStructure.ViewNode ->
        children.forEach { childNode: AssistStructure.ViewNode ->
            traverseNode(childNode, cmRequests)
        }
    }

    private fun getCredentialOptionsFromViewNode(viewNode: AssistStructure.ViewNode?):
            List<CredentialOption> {
    private fun getCredentialOptionsFromViewNode(
            viewNode: AssistStructure.ViewNode,
            autofillId: AutofillId
    ): List<CredentialOption> {
        // TODO(b/293945193) Replace with isCredential check from viewNode
        val credentialHints: MutableList<String> = mutableListOf()
        if (viewNode != null && viewNode.autofillHints != null) {
        if (viewNode.autofillHints != null) {
            for (hint in viewNode.autofillHints!!) {
                if (hint.startsWith(CRED_HINT_PREFIX)) {
                    credentialHints.add(hint.substringAfter(CRED_HINT_PREFIX))
@@ -159,12 +165,14 @@ class CredentialAutofillService : AutofillService() {

        val credentialOptions: MutableList<CredentialOption> = mutableListOf()
        for (credentialHint in credentialHints) {
            convertJsonToCredentialOption(credentialHint).let { credentialOptions.addAll(it) }
            convertJsonToCredentialOption(credentialHint, autofillId)
                    .let { credentialOptions.addAll(it) }
        }
        return credentialOptions
    }

    private fun convertJsonToCredentialOption(jsonString: String): List<CredentialOption> {
    private fun convertJsonToCredentialOption(jsonString: String, autofillId: AutofillId):
            List<CredentialOption> {
        // TODO(b/302000646) Move this logic to jetpack so that is consistent
        //  with building the json
        val credentialOptions: MutableList<CredentialOption> = mutableListOf()
@@ -173,11 +181,14 @@ class CredentialAutofillService : AutofillService() {
        val options = json.getJSONArray(CRED_OPTIONS_KEY)
        for (i in 0 until options.length()) {
            val option = options.getJSONObject(i)

            val candidateBundle = convertJsonToBundle(option.getJSONObject(CANDIDATE_DATA_KEY))
            candidateBundle.putParcelable(
                    CredentialProviderService.EXTRA_AUTOFILL_ID,
                    autofillId)
            credentialOptions.add(CredentialOption(
                    option.getString(TYPE_KEY),
                    convertJsonToBundle(option.getJSONObject(REQUEST_DATA_KEY)),
                    convertJsonToBundle(option.getJSONObject(CANDIDATE_DATA_KEY)),
                    candidateBundle,
                    option.getBoolean(SYS_PROVIDER_REQ_KEY),
            ))
        }
+16 −4
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.credentials.ui.Entry;
import android.credentials.ui.GetCredentialProviderData;
import android.credentials.ui.ProviderPendingIntentResponse;
import android.os.ICancellationSignal;
import android.service.autofill.Flags;
import android.service.credentials.Action;
import android.service.credentials.BeginGetCredentialOption;
import android.service.credentials.BeginGetCredentialRequest;
@@ -42,6 +43,7 @@ import android.service.credentials.GetCredentialRequest;
import android.service.credentials.RemoteEntry;
import android.util.Pair;
import android.util.Slog;
import android.view.autofill.AutofillId;

import java.util.ArrayList;
import java.util.HashMap;
@@ -379,13 +381,23 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
        // but does not resolve to a valid option. For now, not skipping it because
        // it may be possible that the provider adds their own extras and expects to receive
        // those and complete the flow.
        if (mBeginGetOptionToCredentialOptionMap.get(id) == null) {
        Intent intent = new Intent();
        CredentialOption credentialOption = mBeginGetOptionToCredentialOptionMap.get(id);
        if (credentialOption == null) {
            Slog.w(TAG, "Id from Credential Entry does not resolve to a valid option");
            return new Intent();
            return intent;
        }
        return new Intent().putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_REQUEST,
        AutofillId autofillId = credentialOption
                .getCandidateQueryData()
                .getParcelable(CredentialProviderService.EXTRA_AUTOFILL_ID, AutofillId.class);
        if (autofillId != null && Flags.autofillCredmanIntegration()) {
            intent.putExtra(CredentialProviderService.EXTRA_AUTOFILL_ID, autofillId);
        }
        return intent.putExtra(
                CredentialProviderService.EXTRA_GET_CREDENTIAL_REQUEST,
                new GetCredentialRequest(
                        mCallingAppInfo, List.of(mBeginGetOptionToCredentialOptionMap.get(id))));
                        mCallingAppInfo,
                        List.of(credentialOption)));
    }

    private Intent setUpFillInIntentWithQueryRequest() {