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

Commit 9eb577e6 authored by Reema Bajwa's avatar Reema Bajwa
Browse files

Refactor origin to request object for the credential manager privilege APIs

Bug: 268534702
DetailedCoverageBugs: 255429881, 255429478
Test: local-deployment

Change-Id: Id40024989f19d3bd806201b0007b301185064b76
parent 79d1135c
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -13576,17 +13576,26 @@ package android.credentials {
  }
  public final class CreateCredentialRequest implements android.os.Parcelable {
    ctor public CreateCredentialRequest(@NonNull String, @NonNull android.os.Bundle, @NonNull android.os.Bundle, boolean, boolean);
    method public boolean alwaysSendAppInfoToProvider();
    method public int describeContents();
    method @NonNull public android.os.Bundle getCandidateQueryData();
    method @NonNull public android.os.Bundle getCredentialData();
    method @Nullable public String getOrigin();
    method @NonNull public String getType();
    method public boolean isSystemProviderRequired();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.credentials.CreateCredentialRequest> CREATOR;
  }
  public static final class CreateCredentialRequest.Builder {
    ctor public CreateCredentialRequest.Builder(@NonNull android.os.Bundle, @NonNull android.os.Bundle);
    method @NonNull public android.credentials.CreateCredentialRequest build();
    method @NonNull public android.credentials.CreateCredentialRequest.Builder setAlwaysSendAppInfoToProvider(boolean);
    method @NonNull public android.credentials.CreateCredentialRequest.Builder setIsSystemProviderRequired(boolean);
    method @NonNull @RequiresPermission(android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN) public android.credentials.CreateCredentialRequest.Builder setOrigin(@NonNull String);
    method @NonNull public android.credentials.CreateCredentialRequest.Builder setType(@NonNull String);
  }
  public final class CreateCredentialResponse implements android.os.Parcelable {
    ctor public CreateCredentialResponse(@NonNull android.os.Bundle);
    method public int describeContents();
@@ -13618,9 +13627,7 @@ package android.credentials {
  public final class CredentialManager {
    method public void clearCredentialState(@NonNull android.credentials.ClearCredentialStateRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.credentials.ClearCredentialStateException>);
    method public void createCredential(@NonNull android.credentials.CreateCredentialRequest, @NonNull android.app.Activity, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.CreateCredentialResponse,android.credentials.CreateCredentialException>);
    method @RequiresPermission(android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN) public void createCredentialWithOrigin(@NonNull android.credentials.CreateCredentialRequest, @Nullable String, @NonNull android.app.Activity, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.CreateCredentialResponse,android.credentials.CreateCredentialException>);
    method public void getCredential(@NonNull android.credentials.GetCredentialRequest, @NonNull android.app.Activity, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.GetCredentialResponse,android.credentials.GetCredentialException>);
    method @RequiresPermission(android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN) public void getCredentialWithOrigin(@NonNull android.credentials.GetCredentialRequest, @Nullable String, @NonNull android.app.Activity, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.GetCredentialResponse,android.credentials.GetCredentialException>);
    method public boolean isEnabledCredentialProviderService(@NonNull android.content.ComponentName);
    method public void registerCredentialDescription(@NonNull android.credentials.RegisterCredentialDescriptionRequest);
    method public void unregisterCredentialDescription(@NonNull android.credentials.UnregisterCredentialDescriptionRequest);
@@ -13655,6 +13662,7 @@ package android.credentials {
    method public int describeContents();
    method @NonNull public java.util.List<android.credentials.CredentialOption> getCredentialOptions();
    method @NonNull public android.os.Bundle getData();
    method @Nullable public String getOrigin();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.credentials.GetCredentialRequest> CREATOR;
  }
@@ -13665,6 +13673,7 @@ package android.credentials {
    method @NonNull public android.credentials.GetCredentialRequest build();
    method @NonNull public android.credentials.GetCredentialRequest.Builder setAlwaysSendAppInfoToProvider(boolean);
    method @NonNull public android.credentials.GetCredentialRequest.Builder setCredentialOptions(@NonNull java.util.List<android.credentials.CredentialOption>);
    method @NonNull @RequiresPermission(android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN) public android.credentials.GetCredentialRequest.Builder setOrigin(@NonNull String);
  }
  public final class GetCredentialResponse implements android.os.Parcelable {
@@ -40560,7 +40569,9 @@ package android.service.credentials {
  public final class CallingAppInfo implements android.os.Parcelable {
    ctor public CallingAppInfo(@NonNull String, @NonNull android.content.pm.SigningInfo);
    ctor public CallingAppInfo(@NonNull String, @NonNull android.content.pm.SigningInfo, @Nullable String);
    method public int describeContents();
    method @Nullable public String getOrigin();
    method @NonNull public String getPackageName();
    method @NonNull public android.content.pm.SigningInfo getSigningInfo();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
+131 −2
Original line number Diff line number Diff line
@@ -16,9 +16,14 @@

package android.credentials;

import static android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN;

import static java.util.Objects.requireNonNull;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -68,6 +73,14 @@ public final class CreateCredentialRequest implements Parcelable {
     */
    private final boolean mIsSystemProviderRequired;

    /**
     * The origin of the calling app. Callers of this special API (e.g. browsers)
     * can set this origin for an app different from their own, to be able to get credentials
     * on behalf of that app.
     */
    @Nullable
    private final String mOrigin;

    /**
     * Returns the requested credential type.
     */
@@ -123,6 +136,14 @@ public final class CreateCredentialRequest implements Parcelable {
        return mAlwaysSendAppInfoToProvider;
    }

    /**
     * Returns the origin of the calling app if set otherwise returns null.
     */
    @Nullable
    public String getOrigin() {
        return mOrigin;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeString8(mType);
@@ -130,6 +151,7 @@ public final class CreateCredentialRequest implements Parcelable {
        dest.writeBundle(mCandidateQueryData);
        dest.writeBoolean(mIsSystemProviderRequired);
        dest.writeBoolean(mAlwaysSendAppInfoToProvider);
        dest.writeString8(mOrigin);
    }

    @Override
@@ -146,6 +168,7 @@ public final class CreateCredentialRequest implements Parcelable {
                + ", isSystemProviderRequired=" + mIsSystemProviderRequired
                + ", alwaysSendAppInfoToProvider="
                + mAlwaysSendAppInfoToProvider
                + ", origin=" + mOrigin
                + "}";
    }

@@ -165,21 +188,26 @@ public final class CreateCredentialRequest implements Parcelable {
     *                                    the query phase, and will only be sent along
     *                                    with the final request, after the user has selected
     *                                    an entry on the UI.
     * @param origin the origin of the calling app. Callers of this special setter (e.g. browsers)
     *               can set this origin for an app different from their own, to be able to get
     *               credentials on behalf of that app.
     *
     * @throws IllegalArgumentException If type is empty.
     */
    public CreateCredentialRequest(
    private CreateCredentialRequest(
            @NonNull String type,
            @NonNull Bundle credentialData,
            @NonNull Bundle candidateQueryData,
            boolean isSystemProviderRequired,
            boolean alwaysSendAppInfoToProvider) {
            boolean alwaysSendAppInfoToProvider,
            @NonNull String origin) {
        mType = Preconditions.checkStringNotEmpty(type, "type must not be empty");
        mCredentialData = requireNonNull(credentialData, "credentialData must not be null");
        mCandidateQueryData = requireNonNull(candidateQueryData,
                "candidateQueryData must not be null");
        mIsSystemProviderRequired = isSystemProviderRequired;
        mAlwaysSendAppInfoToProvider = alwaysSendAppInfoToProvider;
        mOrigin = origin;
    }

    private CreateCredentialRequest(@NonNull Parcel in) {
@@ -188,6 +216,7 @@ public final class CreateCredentialRequest implements Parcelable {
        Bundle candidateQueryData = in.readBundle();
        boolean isSystemProviderRequired = in.readBoolean();
        boolean alwaysSendAppInfoToProvider = in.readBoolean();
        mOrigin = in.readString8();

        mType = type;
        AnnotationValidations.validate(NonNull.class, null, mType);
@@ -211,4 +240,104 @@ public final class CreateCredentialRequest implements Parcelable {
            return new CreateCredentialRequest(in);
        }
    };

    /** A builder for {@link CreateCredentialRequest}. */
    public static final class Builder {

        private boolean mAlwaysSendAppInfoToProvider;

        @NonNull
        private String mType;

        @NonNull
        private final Bundle mCredentialData;

        @NonNull
        private final Bundle mCandidateQueryData;

        private boolean mIsSystemProviderRequired;

        private String mOrigin;

        /**
         * @param credentialData the full credential creation request data
         * @param candidateQueryData the partial request data that will be sent to the provider
         *                           during the initial creation candidate query stage
         */
        public Builder(@NonNull Bundle credentialData, @NonNull Bundle candidateQueryData) {
            mCredentialData = requireNonNull(credentialData,
                    "credentialData must not be null");
            mCandidateQueryData = requireNonNull(candidateQueryData,
                    "candidateQueryData must not be null");
        }

        /**
         * Sets a true/false value to determine if the calling app info should be
         * removed from the request that is sent to the providers.
         *
         * Developers must set this to false if they wish to remove the
         * {@link android.service.credentials.CallingAppInfo} from the query phases requests that
         * providers receive. Note that the calling app info will still be sent in the
         * final phase after the user has made a selection on the UI.
         *
         * If not set, the default value will be true and the calling app info will be
         * propagated to the providers in every phase.
         */
        @SuppressLint("MissingGetterMatchingBuilder")
        @NonNull
        public CreateCredentialRequest.Builder setAlwaysSendAppInfoToProvider(boolean value) {
            mAlwaysSendAppInfoToProvider = value;
            return this;
        }

        /**
         * Sets the requested credential type.
         */
        @SuppressLint("MissingGetterMatchingBuilder")
        @NonNull
        public CreateCredentialRequest.Builder setType(@NonNull String type) {
            mType = type;
            return this;
        }

        /**
         * Sets whether the request must only be fulfilled by a system provider.
         * This defaults to false
         */
        @SuppressLint("MissingGetterMatchingBuilder")
        @NonNull
        public CreateCredentialRequest.Builder setIsSystemProviderRequired(boolean value) {
            mIsSystemProviderRequired = value;
            return this;
        }

        /**
         * Sets the origin of the calling app. Callers of this special setter (e.g. browsers)
         * can set this origin for an app different from their own, to be able to get
         * credentials on behalf of that app. The permission check only happens later when this
         * instance is passed and processed by the Credential Manager.
         */
        @SuppressLint({"MissingGetterMatchingBuilder", "AndroidFrameworkRequiresPermission"})
        @RequiresPermission(CREDENTIAL_MANAGER_SET_ORIGIN)
        @NonNull
        public CreateCredentialRequest.Builder setOrigin(@NonNull String origin) {
            mOrigin = origin;
            return this;
        }

        /**
         * Builds a {@link GetCredentialRequest}.
         *
         * @throws IllegalArgumentException If credentialOptions is empty.
         */
        @NonNull
        public CreateCredentialRequest build() {
            Preconditions.checkStringNotEmpty(
                    mType,
                    "type must not be empty");

            return new CreateCredentialRequest(mType, mCredentialData, mCandidateQueryData,
                    mIsSystemProviderRequired, mAlwaysSendAppInfoToProvider, mOrigin);
        }
    }
}
+8 −103
Original line number Diff line number Diff line
@@ -123,6 +123,10 @@ public final class CredentialManager {
     *
     * <p>The execution can potentially launch UI flows to collect user consent to using a
     * credential, display a picker when multiple credentials exist, etc.
     * Callers (e.g. browsers) may optionally set origin in {@link GetCredentialRequest} for an
     * app different from their own, to be able to get credentials on behalf of that app. They would
     * need additional permission {@link CREDENTIAL_MANAGER_SET_ORIGIN}
     * to use this functionality
     *
     * @param request the request specifying type(s) of credentials to get from the user
     * @param activity the activity used to launch any UI needed
@@ -162,62 +166,15 @@ public final class CredentialManager {
        }
    }

    /**
     * Launches the necessary flows to retrieve an app credential from the user, for the given
     * origin.
     *
     * <p>The execution can potentially launch UI flows to collect user consent to using a
     * credential, display a picker when multiple credentials exist, etc.
     *
     * @param request the request specifying type(s) of credentials to get from the user
     * @param origin the origin of the calling app. Callers of this special API (e.g. browsers)
     * can set this origin for an app different from their own, to be able to get credentials
     * on behalf of that app.
     * @param activity the activity used to launch any UI needed
     * @param cancellationSignal an optional signal that allows for cancelling this call
     * @param executor the callback will take place on this {@link Executor}
     * @param callback the callback invoked when the request succeeds or fails
     */
    @RequiresPermission(CREDENTIAL_MANAGER_SET_ORIGIN)
    public void getCredentialWithOrigin(
            @NonNull GetCredentialRequest request,
            @Nullable String origin,
            @NonNull Activity activity,
            @Nullable CancellationSignal cancellationSignal,
            @CallbackExecutor @NonNull Executor executor,
            @NonNull OutcomeReceiver<GetCredentialResponse, GetCredentialException> callback) {
        requireNonNull(request, "request must not be null");
        requireNonNull(activity, "activity must not be null");
        requireNonNull(executor, "executor must not be null");
        requireNonNull(callback, "callback must not be null");

        if (cancellationSignal != null && cancellationSignal.isCanceled()) {
            Log.w(TAG, "getCredential already canceled");
            return;
        }

        ICancellationSignal cancelRemote = null;
        try {
            cancelRemote =
                mService.executeGetCredentialWithOrigin(
                    request,
                    new GetCredentialTransport(activity, executor, callback),
                    mContext.getOpPackageName(),
                    origin);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }

        if (cancellationSignal != null && cancelRemote != null) {
            cancellationSignal.setRemote(cancelRemote);
        }
    }

    /**
     * Launches the necessary flows to register an app credential for the user.
     *
     * <p>The execution can potentially launch UI flows to collect user consent to creating or
     * storing the new credential, etc.
     * Callers (e.g. browsers) may optionally set origin in {@link CreateCredentialRequest} for an
     * app different from their own, to be able to get credentials on behalf of that app. They would
     * need additional permission {@link CREDENTIAL_MANAGER_SET_ORIGIN}
     * to use this functionality
     *
     * @param request the request specifying type(s) of credentials to get from the user
     * @param activity the activity used to launch any UI needed
@@ -258,58 +215,6 @@ public final class CredentialManager {
        }
    }

    /**
     * Launches the necessary flows to register an app credential for the user.
     *
     * <p>The execution can potentially launch UI flows to collect user consent to creating or
     * storing the new credential, etc.
     *
     * @param request the request specifying type(s) of credentials to get from the user, for the
     * given origin
     * @param origin the origin of the calling app. Callers of this special API (e.g. browsers)
     * can set this origin for an app different from their own, to be able to get credentials
     * on behalf of that app.
     * @param activity the activity used to launch any UI needed
     * @param cancellationSignal an optional signal that allows for cancelling this call
     * @param executor the callback will take place on this {@link Executor}
     * @param callback the callback invoked when the request succeeds or fails
     */
    @RequiresPermission(CREDENTIAL_MANAGER_SET_ORIGIN)
    public void createCredentialWithOrigin(
            @NonNull CreateCredentialRequest request,
            @Nullable String origin,
            @NonNull Activity activity,
            @Nullable CancellationSignal cancellationSignal,
            @CallbackExecutor @NonNull Executor executor,
            @NonNull
            OutcomeReceiver<CreateCredentialResponse, CreateCredentialException> callback) {
        requireNonNull(request, "request must not be null");
        requireNonNull(activity, "activity must not be null");
        requireNonNull(executor, "executor must not be null");
        requireNonNull(callback, "callback must not be null");

        if (cancellationSignal != null && cancellationSignal.isCanceled()) {
            Log.w(TAG, "createCredential already canceled");
            return;
        }

        ICancellationSignal cancelRemote = null;
        try {
            cancelRemote =
                mService.executeCreateCredentialWithOrigin(
                    request,
                    new CreateCredentialTransport(activity, executor, callback),
                    mContext.getOpPackageName(),
                    origin);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }

        if (cancellationSignal != null && cancelRemote != null) {
            cancellationSignal.setRemote(cancelRemote);
        }
    }

    /**
     * Clears the current user credential state from all credential providers.
     *
+42 −2
Original line number Diff line number Diff line
@@ -16,9 +16,13 @@

package android.credentials;

import static android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN;

import static java.util.Objects.requireNonNull;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Parcel;
@@ -48,6 +52,14 @@ public final class GetCredentialRequest implements Parcelable {
    @NonNull
    private final Bundle mData;

    /**
     * The origin of the calling app. Callers of this special API (e.g. browsers)
     * can set this origin for an app different from their own, to be able to get credentials
     * on behalf of that app.
     */
    @Nullable
    private String mOrigin;

    /**
     * True/False value to determine if the calling app info should be
     * removed from the request that is sent to the providers.
@@ -75,6 +87,14 @@ public final class GetCredentialRequest implements Parcelable {
        return mData;
    }

    /**
     * Returns the origin of the calling app if set otherwise returns null.
     */
    @Nullable
    public String getOrigin() {
        return mOrigin;
    }

    /**
     * Returns a value to determine if the calling app info should be always
     * sent to the provider in every phase (if true), or should be removed
@@ -90,6 +110,7 @@ public final class GetCredentialRequest implements Parcelable {
        dest.writeTypedList(mCredentialOptions, flags);
        dest.writeBundle(mData);
        dest.writeBoolean(mAlwaysSendAppInfoToProvider);
        dest.writeString8(mOrigin);
    }

    @Override
@@ -103,11 +124,12 @@ public final class GetCredentialRequest implements Parcelable {
                + ", data=" + mData
                + ", alwaysSendAppInfoToProvider="
                + mAlwaysSendAppInfoToProvider
                + ", origin=" + mOrigin
                + "}";
    }

    private GetCredentialRequest(@NonNull List<CredentialOption> credentialOptions,
            @NonNull Bundle data, @NonNull boolean alwaysSendAppInfoToProvider) {
            @NonNull Bundle data, @NonNull boolean alwaysSendAppInfoToProvider, String origin) {
        Preconditions.checkCollectionNotEmpty(
                credentialOptions,
                /*valueName=*/ "credentialOptions");
@@ -118,6 +140,7 @@ public final class GetCredentialRequest implements Parcelable {
        mData = requireNonNull(data,
                "data must not be null");
        mAlwaysSendAppInfoToProvider = alwaysSendAppInfoToProvider;
        mOrigin = origin;
    }

    private GetCredentialRequest(@NonNull Parcel in) {
@@ -132,6 +155,7 @@ public final class GetCredentialRequest implements Parcelable {
        AnnotationValidations.validate(NonNull.class, null, mData);

        mAlwaysSendAppInfoToProvider = in.readBoolean();
        mOrigin = in.readString8();
    }

    @NonNull public static final Parcelable.Creator<GetCredentialRequest> CREATOR =
@@ -159,6 +183,8 @@ public final class GetCredentialRequest implements Parcelable {
        @NonNull
        private boolean mAlwaysSendAppInfoToProvider = true;

        private String mOrigin;

        /**
         * @param data the top request level data
         */
@@ -208,6 +234,20 @@ public final class GetCredentialRequest implements Parcelable {
            return this;
        }

        /**
         * Sets the origin of the calling app. Callers of this special setter (e.g. browsers)
         * can set this origin for an app different from their own, to be able to get
         * credentials on behalf of that app. The permission check only happens later when this
         * instance is passed and processed by the Credential Manager.
         */
        @SuppressLint({"MissingGetterMatchingBuilder", "AndroidFrameworkRequiresPermission"})
        @RequiresPermission(CREDENTIAL_MANAGER_SET_ORIGIN)
        @NonNull
        public Builder setOrigin(@NonNull String origin) {
            mOrigin = origin;
            return this;
        }

        /**
         * Builds a {@link GetCredentialRequest}.
         *
@@ -222,7 +262,7 @@ public final class GetCredentialRequest implements Parcelable {
                    mCredentialOptions,
                    /*valueName=*/ "credentialOptions");
            return new GetCredentialRequest(mCredentialOptions, mData,
                    mAlwaysSendAppInfoToProvider);
                    mAlwaysSendAppInfoToProvider, mOrigin);
        }
    }
}
+0 −4
Original line number Diff line number Diff line
@@ -41,12 +41,8 @@ interface ICredentialManager {

    @nullable ICancellationSignal executeGetCredential(in GetCredentialRequest request, in IGetCredentialCallback callback, String callingPackage);

    @nullable ICancellationSignal executeGetCredentialWithOrigin(in GetCredentialRequest request, in IGetCredentialCallback callback, String callingPackage, String origin);

    @nullable ICancellationSignal executeCreateCredential(in CreateCredentialRequest request, in ICreateCredentialCallback callback, String callingPackage);

    @nullable ICancellationSignal executeCreateCredentialWithOrigin(in CreateCredentialRequest request, in ICreateCredentialCallback callback, String callingPackage, String origin);

    @nullable ICancellationSignal clearCredentialState(in ClearCredentialStateRequest request, in IClearCredentialStateCallback callback, String callingPackage);

    @nullable ICancellationSignal listEnabledProviders(in IListEnabledProvidersCallback callback);
Loading