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

Commit 694fd0f2 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Maintain auth entry status across providers" into udc-dev am: d77e0d99

parents 56531f3c d77e0d99
Loading
Loading
Loading
Loading
+36 −1
Original line number Original line Diff line number Diff line
@@ -44,7 +44,6 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
        IGetCredentialCallback>
        IGetCredentialCallback>
        implements ProviderSession.ProviderInternalCallback<GetCredentialResponse> {
        implements ProviderSession.ProviderInternalCallback<GetCredentialResponse> {
    private static final String TAG = "GetRequestSession";
    private static final String TAG = "GetRequestSession";

    public GetRequestSession(Context context, int userId, int callingUid,
    public GetRequestSession(Context context, int userId, int callingUid,
            IGetCredentialCallback callback, GetCredentialRequest request,
            IGetCredentialCallback callback, GetCredentialRequest request,
            CallingAppInfo callingAppInfo, CancellationSignal cancellationSignal) {
            CallingAppInfo callingAppInfo, CancellationSignal cancellationSignal) {
@@ -173,6 +172,12 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
    public void onProviderStatusChanged(ProviderSession.Status status,
    public void onProviderStatusChanged(ProviderSession.Status status,
            ComponentName componentName) {
            ComponentName componentName) {
        Log.i(TAG, "in onStatusChanged with status: " + status);
        Log.i(TAG, "in onStatusChanged with status: " + status);
        // Auth entry was selected, and it did not have any underlying credentials
        if (status == ProviderSession.Status.NO_CREDENTIALS_FROM_AUTH_ENTRY) {
            handleEmptyAuthenticationSelection(componentName);
            return;
        }
        // For any other status, we check if all providers are done and then invoke UI if needed
        if (!isAnyProviderPending()) {
        if (!isAnyProviderPending()) {
            // If all provider responses have been received, we can either need the UI,
            // If all provider responses have been received, we can either need the UI,
            // or we need to respond with error. The only other case is the entry being
            // or we need to respond with error. The only other case is the entry being
@@ -186,4 +191,34 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
            }
            }
        }
        }
    }
    }

    private void handleEmptyAuthenticationSelection(ComponentName componentName) {
        // Update auth entry statuses across different provider sessions
        mProviders.keySet().forEach(key -> {
            ProviderGetSession session = (ProviderGetSession) mProviders.get(key);
            if (!session.mComponentName.equals(componentName)) {
                session.updateAuthEntriesStatusFromAnotherSession();
            }
        });

        // Invoke UI since it needs to show a snackbar if last auth entry, or a status on each
        // auth entries along with other valid entries
        getProviderDataAndInitiateUi();

        // Respond to client if all auth entries are empty and nothing else to show on the UI
        if (providerDataContainsEmptyAuthEntriesOnly()) {
            respondToClientWithErrorAndFinish(GetCredentialException.TYPE_NO_CREDENTIAL,
                    "No credentials available");
        }
    }

    private boolean providerDataContainsEmptyAuthEntriesOnly() {
        for (String key : mProviders.keySet()) {
            ProviderGetSession session = (ProviderGetSession) mProviders.get(key);
            if (!session.containsEmptyAuthEntriesOnly()) {
                return false;
            }
        }
        return true;
    }
}
}
+31 −4
Original line number Original line Diff line number Diff line
@@ -241,13 +241,14 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
                if (additionalContentReceived) {
                if (additionalContentReceived) {
                    Log.i(TAG, "Additional content received - removing authentication entry");
                    Log.i(TAG, "Additional content received - removing authentication entry");
                    mProviderResponseDataHandler.removeAuthenticationAction(entryKey);
                    mProviderResponseDataHandler.removeAuthenticationAction(entryKey);
                    if (!mProviderResponseDataHandler.isEmptyResponse()) {
                        updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
                    }
                } else {
                } else {
                    Log.i(TAG, "Additional content not received");
                    Log.i(TAG, "Additional content not received");
                    mProviderResponseDataHandler
                    mProviderResponseDataHandler
                            .updateAuthEntryWithNoCredentialsReceived(entryKey);
                            .updateAuthEntryWithNoCredentialsReceived(entryKey);
                }
                    updateStatusAndInvokeCallback(Status.NO_CREDENTIALS_FROM_AUTH_ENTRY);
                if (!mProviderResponseDataHandler.isEmptyResponse()) {
                    updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
                }
                }
                break;
                break;
            case REMOTE_ENTRY_KEY:
            case REMOTE_ENTRY_KEY:
@@ -456,6 +457,27 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
                GetCredentialException.TYPE_UNKNOWN, null);
                GetCredentialException.TYPE_UNKNOWN, null);
    }
    }


    /** Update auth entries status based on an auth entry selected from a different session. */
    public void updateAuthEntriesStatusFromAnotherSession() {
        // Pass null for entryKey if the auth entry selected belongs to a different session
        mProviderResponseDataHandler.updateAuthEntryWithNoCredentialsReceived(/*entryKey=*/null);
    }

    /** Returns true if the provider response contains empty auth entries only, false otherwise. **/
    public boolean containsEmptyAuthEntriesOnly() {
        // We do not consider action entries here because if actions are the only entries,
        // we don't show the UI
        return mProviderResponseDataHandler.mUiCredentialEntries.isEmpty()
                && mProviderResponseDataHandler.mUiRemoteEntry == null
                && mProviderResponseDataHandler.mUiAuthenticationEntries
                .values().stream().allMatch(
                        e -> e.second.getStatus() == AuthenticationEntry
                                .STATUS_UNLOCKED_BUT_EMPTY_LESS_RECENT
                                || e.second.getStatus()
                                == AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_MOST_RECENT
        );
    }

    private class ProviderResponseDataHandler {
    private class ProviderResponseDataHandler {
        private final ComponentName mExpectedRemoteEntryProviderService;
        private final ComponentName mExpectedRemoteEntryProviderService;
        @NonNull
        @NonNull
@@ -610,7 +632,12 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
                    ? null : mUiCredentialEntries.get(entryKey).first;
                    ? null : mUiCredentialEntries.get(entryKey).first;
        }
        }


        public void updateAuthEntryWithNoCredentialsReceived(String entryKey) {
        public void updateAuthEntryWithNoCredentialsReceived(@Nullable String entryKey) {
            if (entryKey == null) {
                // Auth entry from a different provider was selected by the user.
                updatePreviousMostRecentAuthEntry();
                return;
            }
            updatePreviousMostRecentAuthEntry();
            updatePreviousMostRecentAuthEntry();
            updateMostRecentAuthEntry(entryKey);
            updateMostRecentAuthEntry(entryKey);
        }
        }
+3 −2
Original line number Original line Diff line number Diff line
@@ -66,7 +66,8 @@ public abstract class ProviderSession<T, R>
     * on the credMan UI.
     * on the credMan UI.
     */
     */
    public static boolean isUiInvokingStatus(Status status) {
    public static boolean isUiInvokingStatus(Status status) {
        return status == Status.CREDENTIALS_RECEIVED || status == Status.SAVE_ENTRIES_RECEIVED;
        return status == Status.CREDENTIALS_RECEIVED || status == Status.SAVE_ENTRIES_RECEIVED
                || status == Status.NO_CREDENTIALS_FROM_AUTH_ENTRY;
    }
    }


    /**
    /**
@@ -140,7 +141,7 @@ public abstract class ProviderSession<T, R>
        PENDING_INTENT_INVOKED,
        PENDING_INTENT_INVOKED,
        CREDENTIAL_RECEIVED_FROM_SELECTION,
        CREDENTIAL_RECEIVED_FROM_SELECTION,
        SAVE_ENTRIES_RECEIVED, CANCELED,
        SAVE_ENTRIES_RECEIVED, CANCELED,
        NO_CREDENTIALS, EMPTY_RESPONSE, COMPLETE
        NO_CREDENTIALS, EMPTY_RESPONSE, NO_CREDENTIALS_FROM_AUTH_ENTRY, COMPLETE
    }
    }


    /** Converts exception to a provider session status. */
    /** Converts exception to a provider session status. */
+1 −1
Original line number Original line Diff line number Diff line
@@ -216,7 +216,7 @@ abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialMan
     * Returns true if at least one provider is ready for UI invocation, and no
     * Returns true if at least one provider is ready for UI invocation, and no
     * provider is pending a response.
     * provider is pending a response.
     */
     */
    boolean isUiInvocationNeeded() {
    protected boolean isUiInvocationNeeded() {
        for (ProviderSession session : mProviders.values()) {
        for (ProviderSession session : mProviders.values()) {
            if (ProviderSession.isUiInvokingStatus(session.getStatus())) {
            if (ProviderSession.isUiInvokingStatus(session.getStatus())) {
                return true;
                return true;