diff options
| author | 2023-03-08 19:00:12 +0000 | |
|---|---|---|
| committer | 2023-03-08 19:00:12 +0000 | |
| commit | e9a096d2a79d32f04118333d3fd111da33d91175 (patch) | |
| tree | 157ddc763a7dca421dcaebcad9e54208c1ce6656 | |
| parent | 4a3be7ee9703bfb2974945e16e98e37101e69bd8 (diff) | |
| parent | 5e2914e8f8d45fd99952b669fb6190d31e62209e (diff) | |
Merge "Adding tests for ProviderRegistryGetSession" into udc-dev
7 files changed, 436 insertions, 19 deletions
diff --git a/core/java/android/service/credentials/CredentialProviderInfoFactory.java b/core/java/android/service/credentials/CredentialProviderInfoFactory.java index fd9360f00d4a..9cd5aa06463a 100644 --- a/core/java/android/service/credentials/CredentialProviderInfoFactory.java +++ b/core/java/android/service/credentials/CredentialProviderInfoFactory.java @@ -41,6 +41,8 @@ import android.os.UserHandle; import android.util.Log; import android.util.Slog; +import com.android.internal.annotations.VisibleForTesting; + import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -115,6 +117,26 @@ public final class CredentialProviderInfoFactory { .build(); } + /** + * Constructs an information instance of the credential provider for testing purposes. Does + * not run any verifications and passes parameters as is. + */ + @VisibleForTesting + public static CredentialProviderInfo createForTests( + @NonNull ServiceInfo serviceInfo, + @NonNull CharSequence overrideLabel, + boolean isSystemProvider, + boolean isEnabled, + @NonNull List<String> capabilities) { + return new CredentialProviderInfo.Builder(serviceInfo) + .setEnabled(isEnabled) + .setOverrideLabel(overrideLabel) + .setSystemProvider(isSystemProvider) + .addCapabilities(capabilities) + .build(); + + } + private static void verifyProviderPermission(ServiceInfo serviceInfo) throws SecurityException { final String permission = Manifest.permission.BIND_CREDENTIAL_PROVIDER_SERVICE; if (permission.equals(serviceInfo.permission)) { @@ -349,6 +371,31 @@ public final class CredentialProviderInfoFactory { } /** + * Returns a valid credential provider that has the given package name. Returns null if no + * match is found. + */ + @Nullable + public static CredentialProviderInfo getCredentialProviderFromPackageName( + @NonNull Context context, + int userId, + @NonNull String packageName, + int providerFilter, + @NonNull Set<ServiceInfo> enabledServices) { + requireNonNull(context, "context must not be null"); + requireNonNull(packageName, "package name must not be null"); + requireNonNull(enabledServices, "enabledServices must not be null"); + + for (CredentialProviderInfo credentialProviderInfo : getCredentialProviderServices(context, + userId, providerFilter, enabledServices)) { + if (credentialProviderInfo.getServiceInfo() + .packageName.equals(packageName)) { + return credentialProviderInfo; + } + } + return null; + } + + /** * Returns the valid credential provider services available for the user with the given {@code * userId}. */ diff --git a/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java b/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java index d768d234cd20..14c49b312f34 100644 --- a/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java +++ b/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java @@ -34,7 +34,7 @@ import java.util.Set; import java.util.concurrent.locks.ReentrantLock; /** Contains information on what CredentialProvider has what provisioned Credential. */ -public final class CredentialDescriptionRegistry { +public class CredentialDescriptionRegistry { private static final int MAX_ALLOWED_CREDENTIAL_DESCRIPTIONS = 128; private static final int MAX_ALLOWED_ENTRIES_PER_PROVIDER = 16; @@ -54,7 +54,8 @@ public final class CredentialDescriptionRegistry { final String mFlattenedRequest; final List<CredentialEntry> mCredentialEntries; - private FilterResult(String packageName, + @VisibleForTesting + FilterResult(String packageName, String flattenedRequest, List<CredentialEntry> credentialEntries) { mPackageName = packageName; @@ -92,10 +93,10 @@ public final class CredentialDescriptionRegistry { } } - /** Clears an existing session for a given user identifier. */ + /** Clears an existing session for a given user identifier. Used when testing only. */ @GuardedBy("sLock") @VisibleForTesting - public static void clearAllSessions() { + static void clearAllSessions() { sLock.lock(); try { sCredentialDescriptionSessionPerUser.clear(); @@ -104,6 +105,19 @@ public final class CredentialDescriptionRegistry { } } + /** Sets an existing session for a given user identifier. Used when testing only. */ + @GuardedBy("sLock") + @VisibleForTesting + static void setSession(int userId, CredentialDescriptionRegistry + credentialDescriptionRegistry) { + sLock.lock(); + try { + sCredentialDescriptionSessionPerUser.put(userId, credentialDescriptionRegistry); + } finally { + sLock.unlock(); + } + } + private Map<String, Set<CredentialDescription>> mCredentialDescriptions; private int mTotalDescriptionCount; diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java index 9c870050449c..6e998c4ef195 100644 --- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java +++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java @@ -296,6 +296,12 @@ public final class CredentialManagerService mContext, UserHandle.getCallingUserId(), session, + CredentialProviderInfoFactory.getCredentialProviderFromPackageName( + mContext, UserHandle.getCallingUserId() , + result.second.mPackageName, + CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS, + new HashSet<>()), + session.mClientAppInfo, result.second.mPackageName, result.first)); } @@ -358,6 +364,14 @@ public final class CredentialManagerService return providerSessions; } + private List<CredentialProviderInfo> getServicesForCredentialDescription(int userId) { + return CredentialProviderInfoFactory.getCredentialProviderServices( + mContext, + userId, + CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS, + new HashSet<>()); + } + @Override @GuardedBy("CredentialDescriptionRegistry.sLock") public void onUserStopped(@NonNull TargetUser user) { @@ -813,14 +827,6 @@ public final class CredentialManagerService session.executeUnregisterRequest(request, callingPackage); } - - private List<CredentialProviderInfo> getServicesForCredentialDescription(int userId) { - return CredentialProviderInfoFactory.getCredentialProviderServices( - mContext, - userId, - CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS, - new HashSet<>()); - } } private void enforceCallingPackage(String callingPackage, int callingUid) { diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java index 8c6e5cea3bba..f59b32c667da 100644 --- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java +++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java @@ -41,7 +41,7 @@ import java.util.ArrayList; * Central session for a single getCredentials request. This class listens to the * responses from providers, and the UX app, and updates the provider(S) state. */ -public final class GetRequestSession extends RequestSession<GetCredentialRequest, +public class GetRequestSession extends RequestSession<GetCredentialRequest, IGetCredentialCallback> implements ProviderSession.ProviderInternalCallback<GetCredentialResponse> { private static final String TAG = "GetRequestSession"; diff --git a/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java index 36d6b3dc7636..457806de7c9f 100644 --- a/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java +++ b/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java @@ -22,6 +22,7 @@ import android.annotation.UserIdInt; import android.content.Context; import android.content.Intent; import android.credentials.CredentialOption; +import android.credentials.CredentialProviderInfo; import android.credentials.GetCredentialException; import android.credentials.GetCredentialResponse; import android.credentials.ui.Entry; @@ -33,6 +34,8 @@ import android.service.credentials.CredentialEntry; import android.service.credentials.CredentialProviderService; import android.telecom.Log; +import com.android.internal.annotations.VisibleForTesting; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -52,7 +55,8 @@ public class ProviderRegistryGetSession extends ProviderSession<CredentialOption Set<CredentialDescriptionRegistry.FilterResult>> { private static final String TAG = "ProviderRegistryGetSession"; - private static final String CREDENTIAL_ENTRY_KEY = "credential_key"; + @VisibleForTesting + static final String CREDENTIAL_ENTRY_KEY = "credential_key"; /** Creates a new provider session to be used by the request session. */ @Nullable @@ -60,13 +64,16 @@ public class ProviderRegistryGetSession extends ProviderSession<CredentialOption @NonNull Context context, @UserIdInt int userId, @NonNull GetRequestSession getRequestSession, + @NonNull CredentialProviderInfo credentialProviderInfo, + @NonNull CallingAppInfo callingAppInfo, @NonNull String credentialProviderPackageName, @NonNull CredentialOption requestOption) { return new ProviderRegistryGetSession( context, userId, getRequestSession, - getRequestSession.mClientAppInfo, + credentialProviderInfo, + callingAppInfo, credentialProviderPackageName, requestOption); } @@ -81,15 +88,17 @@ public class ProviderRegistryGetSession extends ProviderSession<CredentialOption private final String mCredentialProviderPackageName; @NonNull private final String mFlattenedRequestOptionString; - private List<CredentialEntry> mCredentialEntries; + @VisibleForTesting + List<CredentialEntry> mCredentialEntries; protected ProviderRegistryGetSession(@NonNull Context context, @NonNull int userId, @NonNull GetRequestSession session, + @NonNull CredentialProviderInfo credentialProviderInfo, @NonNull CallingAppInfo callingAppInfo, @NonNull String servicePackageName, @NonNull CredentialOption requestOption) { - super(context, null, requestOption, session, userId, null); + super(context, credentialProviderInfo, requestOption, session, userId, null); mCredentialDescriptionRegistry = CredentialDescriptionRegistry.forUser(userId); mCallingAppInfo = callingAppInfo; mCredentialProviderPackageName = servicePackageName; @@ -183,7 +192,7 @@ public class ProviderRegistryGetSession extends ProviderSession<CredentialOption providerPendingIntentResponse.getResultData()); if (getCredentialResponse != null) { if (mCallbacks != null) { - mCallbacks.onFinalResponseReceived(mComponentName, + ((GetRequestSession) mCallbacks).onFinalResponseReceived(mComponentName, getCredentialResponse); } return; diff --git a/services/credentials/java/com/android/server/credentials/ProviderSession.java b/services/credentials/java/com/android/server/credentials/ProviderSession.java index a85769572972..a8b9bf6b1fd6 100644 --- a/services/credentials/java/com/android/server/credentials/ProviderSession.java +++ b/services/credentials/java/com/android/server/credentials/ProviderSession.java @@ -114,7 +114,7 @@ public abstract class ProviderSession<T, R> @Nullable String message); } - protected ProviderSession(@NonNull Context context, @NonNull CredentialProviderInfo info, + protected ProviderSession(@NonNull Context context, @Nullable CredentialProviderInfo info, @NonNull T providerRequest, @Nullable ProviderInternalCallback callbacks, @NonNull int userId, diff --git a/services/tests/servicestests/src/com/android/server/credentials/ProviderRegistryGetSessionTest.java b/services/tests/servicestests/src/com/android/server/credentials/ProviderRegistryGetSessionTest.java new file mode 100644 index 000000000000..3d52ac558605 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/credentials/ProviderRegistryGetSessionTest.java @@ -0,0 +1,341 @@ +/* + * 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.server.credentials; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertThrows; + +import android.app.Activity; +import android.app.slice.Slice; +import android.app.slice.SliceSpec; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ServiceInfo; +import android.content.pm.Signature; +import android.content.pm.SigningDetails; +import android.content.pm.SigningInfo; +import android.credentials.Credential; +import android.credentials.CredentialOption; +import android.credentials.CredentialProviderInfo; +import android.credentials.GetCredentialException; +import android.credentials.GetCredentialResponse; +import android.credentials.ui.GetCredentialProviderData; +import android.credentials.ui.ProviderPendingIntentResponse; +import android.net.Uri; +import android.os.Bundle; +import android.service.credentials.CallingAppInfo; +import android.service.credentials.CredentialEntry; +import android.service.credentials.CredentialProviderInfoFactory; +import android.service.credentials.CredentialProviderService; +import android.service.credentials.GetCredentialRequest; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.security.cert.CertificateException; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Tests for CredentialDescriptionRegistry. + * + * atest FrameworksServicesTests:com.android.server.credentials.ProviderRegistryGetSessionTest + */ +@RunWith(AndroidJUnit4.class) +@SmallTest +public class ProviderRegistryGetSessionTest { + + private static final String CALLING_PACKAGE_NAME = "com.credman.app"; + private static final int USER_ID_1 = 1; + private static final String FLATTENED_REQUEST = "FLATTENED_REQ"; + private static final String CP_SERVICE_NAME = "CredentialProvider"; + private static final ComponentName CREDENTIAL_PROVIDER_COMPONENT = + new ComponentName(CALLING_PACKAGE_NAME, CP_SERVICE_NAME); + private static final String GET_CREDENTIAL_EXCEPTION_TYPE = "TYPE"; + private static final String CREDENTIAL_TYPE = "MDOC"; + private static final String GET_CREDENTIAL_EXCEPTION_MESSAGE = "MESSAGE"; + + private ProviderRegistryGetSession mProviderRegistryGetSession; + @Mock private GetRequestSession mGetRequestSession; + private CredentialOption mGetCredentialOption; + @Mock private ServiceInfo mServiceInfo; + private CredentialProviderInfo mCredentialProviderInfo; + private CallingAppInfo mCallingAppInfo; + @Mock private CredentialDescriptionRegistry mCredentialDescriptionRegistry; + private Bundle mRetrievalData; + @Mock private CredentialEntry mEntry; + @Mock private CredentialEntry mEntry2; + private Slice mSlice; + private Slice mSlice2; + private CredentialDescriptionRegistry.FilterResult mResult; + private Set<CredentialDescriptionRegistry.FilterResult> mResponse; + + @SuppressWarnings("GuardedBy") + @Before + public void setUp() throws CertificateException { + MockitoAnnotations.initMocks(this); + final Context context = ApplicationProvider.getApplicationContext(); + mRetrievalData = new Bundle(); + mRetrievalData.putString(CredentialOption.FLATTENED_REQUEST, FLATTENED_REQUEST); + mCallingAppInfo = createCallingAppInfo(); + mGetCredentialOption = new CredentialOption(CREDENTIAL_TYPE, mRetrievalData, + new Bundle(), false); + when(mServiceInfo.getComponentName()).thenReturn(CREDENTIAL_PROVIDER_COMPONENT); + mCredentialProviderInfo = CredentialProviderInfoFactory + .createForTests(mServiceInfo, + /* overrideLabel= */ "test", + /* isSystemProvider= */ false, + /* isEnabled= */ true, + /* capabilities= */ Collections.EMPTY_LIST); + CredentialDescriptionRegistry.setSession(USER_ID_1, mCredentialDescriptionRegistry); + mResponse = new HashSet<>(); + mSlice = createSlice(); + mSlice2 = createSlice(); + when(mEntry.getSlice()).thenReturn(mSlice); + when(mEntry2.getSlice()).thenReturn(mSlice2); + mResult = new CredentialDescriptionRegistry.FilterResult(CALLING_PACKAGE_NAME, + FLATTENED_REQUEST, + List.of(mEntry, mEntry2)); + mResponse.add(mResult); + when(mCredentialDescriptionRegistry.getFilteredResultForProvider(anyString(), anyString())) + .thenReturn(mResponse); + mProviderRegistryGetSession = ProviderRegistryGetSession + .createNewSession(context, USER_ID_1, mGetRequestSession, mCredentialProviderInfo, + mCallingAppInfo, + CALLING_PACKAGE_NAME, + mGetCredentialOption); + } + + @Test + public void testInvokeSession_existingProvider_setsResults() { + final ArgumentCaptor<String> packageNameCaptor = ArgumentCaptor.forClass(String.class); + final ArgumentCaptor<String> flattenedRequestCaptor = ArgumentCaptor.forClass(String.class); + final ArgumentCaptor<ProviderSession.Status> statusCaptor = + ArgumentCaptor.forClass(ProviderSession.Status.class); + final ArgumentCaptor<ComponentName> cpComponentNameCaptor = + ArgumentCaptor.forClass(ComponentName.class); + + mProviderRegistryGetSession.invokeSession(); + + verify(mCredentialDescriptionRegistry).getFilteredResultForProvider( + packageNameCaptor.capture(), + flattenedRequestCaptor.capture()); + assertThat(packageNameCaptor.getValue()).isEqualTo(CALLING_PACKAGE_NAME); + assertThat(flattenedRequestCaptor.getValue()).isEqualTo(FLATTENED_REQUEST); + verify(mGetRequestSession).onProviderStatusChanged(statusCaptor.capture(), + cpComponentNameCaptor.capture()); + assertThat(statusCaptor.getValue()).isEqualTo(ProviderSession.Status.CREDENTIALS_RECEIVED); + assertThat(cpComponentNameCaptor.getValue()).isEqualTo(CREDENTIAL_PROVIDER_COMPONENT); + assertThat(mProviderRegistryGetSession.mCredentialEntries).hasSize(2); + assertThat(mProviderRegistryGetSession.mCredentialEntries.get(0)).isSameInstanceAs(mEntry); + assertThat(mProviderRegistryGetSession.mCredentialEntries.get(1)).isSameInstanceAs(mEntry2); + } + + @Test + public void testPrepareUiData_statusNonUIInvoking_throwsIllegalStateException() { + mProviderRegistryGetSession.setStatus(ProviderSession.Status.CREDENTIALS_RECEIVED); + + assertThrows(IllegalStateException.class, + () -> mProviderRegistryGetSession.prepareUiData()); + } + + @Test + public void testPrepareUiData_statusUIInvokingNoResults_returnsNull() { + mProviderRegistryGetSession.setStatus(ProviderSession.Status.CANCELED); + + assertThat(mProviderRegistryGetSession.prepareUiData()).isNull(); + } + + @Test + public void testPrepareUiData_invokeCalledSuccessfully_returnsCorrectData() { + mProviderRegistryGetSession.invokeSession(); + GetCredentialProviderData providerData = (GetCredentialProviderData) + mProviderRegistryGetSession.prepareUiData(); + + assertThat(providerData).isNotNull(); + assertThat(providerData.getCredentialEntries()).hasSize(2); + assertThat(providerData.getCredentialEntries().get(0).getSlice()).isSameInstanceAs(mSlice); + assertThat(providerData.getCredentialEntries().get(1).getSlice()).isSameInstanceAs(mSlice2); + Intent intent = providerData.getCredentialEntries().get(0).getFrameworkExtrasIntent(); + GetCredentialRequest getRequest = intent.getParcelableExtra(CredentialProviderService + .EXTRA_GET_CREDENTIAL_REQUEST, GetCredentialRequest.class); + assertThat(getRequest.getCallingAppInfo()).isSameInstanceAs(mCallingAppInfo); + assertThat(getRequest.getCredentialOptions().get(0)).isSameInstanceAs(mGetCredentialOption); + Intent intent2 = providerData.getCredentialEntries().get(0).getFrameworkExtrasIntent(); + GetCredentialRequest getRequest2 = intent2.getParcelableExtra(CredentialProviderService + .EXTRA_GET_CREDENTIAL_REQUEST, GetCredentialRequest.class); + assertThat(getRequest2.getCallingAppInfo()).isSameInstanceAs(mCallingAppInfo); + assertThat(getRequest2.getCredentialOptions().get(0)) + .isSameInstanceAs(mGetCredentialOption); + } + + @Test + public void testOnUiEntrySelected_wrongEntryKey_doesNothing() { + final Intent intent = new Intent(); + final GetCredentialResponse response = + new GetCredentialResponse(new Credential(CREDENTIAL_TYPE, new Bundle())); + intent.putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_RESPONSE, response); + final ProviderPendingIntentResponse providerPendingIntentResponse = new + ProviderPendingIntentResponse(Activity.RESULT_OK, intent); + + mProviderRegistryGetSession.onUiEntrySelected( + ProviderRegistryGetSession.CREDENTIAL_ENTRY_KEY, + "unsupportedKey", providerPendingIntentResponse); + + verifyZeroInteractions(mGetRequestSession); + } + + @Test + public void testOnUiEntrySelected_nullPendingIntentResponse_doesNothing() { + mProviderRegistryGetSession.onUiEntrySelected( + ProviderRegistryGetSession.CREDENTIAL_ENTRY_KEY, + ProviderRegistryGetSession.CREDENTIAL_ENTRY_KEY, null); + + verifyZeroInteractions(mGetRequestSession); + } + + @Test + public void testOnUiEntrySelected_pendingIntentWithException_callbackWithGivenException() { + final ArgumentCaptor<String> exceptionTypeCaptor = + ArgumentCaptor.forClass(String.class); + final ArgumentCaptor<String> exceptionMessageCaptor = + ArgumentCaptor.forClass(String.class); + final ArgumentCaptor<ComponentName> cpComponentNameCaptor = + ArgumentCaptor.forClass(ComponentName.class); + final ArgumentCaptor<ProviderSession.Status> statusCaptor = + ArgumentCaptor.forClass(ProviderSession.Status.class); + final GetCredentialException exception = + new GetCredentialException(GET_CREDENTIAL_EXCEPTION_TYPE, + GET_CREDENTIAL_EXCEPTION_MESSAGE); + mProviderRegistryGetSession.invokeSession(); + GetCredentialProviderData providerData = (GetCredentialProviderData) + mProviderRegistryGetSession.prepareUiData(); + String entryKey = providerData.getCredentialEntries().get(0).getSubkey(); + final Intent intent = new Intent(); + intent.putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_EXCEPTION, exception); + final ProviderPendingIntentResponse providerPendingIntentResponse = new + ProviderPendingIntentResponse(Activity.RESULT_OK, intent); + + mProviderRegistryGetSession.onUiEntrySelected( + ProviderRegistryGetSession.CREDENTIAL_ENTRY_KEY, + entryKey, providerPendingIntentResponse); + + verify(mGetRequestSession).onProviderStatusChanged(statusCaptor.capture(), + cpComponentNameCaptor.capture()); + assertThat(statusCaptor.getValue()).isEqualTo(ProviderSession.Status.CREDENTIALS_RECEIVED); + verify(mGetRequestSession).onFinalErrorReceived(cpComponentNameCaptor.capture(), + exceptionTypeCaptor.capture(), exceptionMessageCaptor.capture()); + assertThat(cpComponentNameCaptor.getValue()) + .isSameInstanceAs(CREDENTIAL_PROVIDER_COMPONENT); + assertThat(exceptionTypeCaptor.getValue()).isEqualTo(GET_CREDENTIAL_EXCEPTION_TYPE); + assertThat(exceptionMessageCaptor.getValue()).isEqualTo(GET_CREDENTIAL_EXCEPTION_MESSAGE); + } + + @Test + public void testOnUiEntrySelected_pendingIntentWithException_callbackWithCancelledException() { + final ArgumentCaptor<String> exceptionTypeCaptor = + ArgumentCaptor.forClass(String.class); + final ArgumentCaptor<String> exceptionMessageCaptor = + ArgumentCaptor.forClass(String.class); + final ArgumentCaptor<ComponentName> cpComponentNameCaptor = + ArgumentCaptor.forClass(ComponentName.class); + final ArgumentCaptor<ProviderSession.Status> statusCaptor = + ArgumentCaptor.forClass(ProviderSession.Status.class); + + mProviderRegistryGetSession.invokeSession(); + GetCredentialProviderData providerData = (GetCredentialProviderData) + mProviderRegistryGetSession.prepareUiData(); + String entryKey = providerData.getCredentialEntries().get(0).getSubkey(); + final Intent intent = new Intent(); + final ProviderPendingIntentResponse providerPendingIntentResponse = new + ProviderPendingIntentResponse(Activity.RESULT_CANCELED, intent); + + mProviderRegistryGetSession.onUiEntrySelected( + ProviderRegistryGetSession.CREDENTIAL_ENTRY_KEY, + entryKey, providerPendingIntentResponse); + + verify(mGetRequestSession).onProviderStatusChanged(statusCaptor.capture(), + cpComponentNameCaptor.capture()); + assertThat(statusCaptor.getValue()).isEqualTo(ProviderSession.Status.CREDENTIALS_RECEIVED); + verify(mGetRequestSession).onFinalErrorReceived(cpComponentNameCaptor.capture(), + exceptionTypeCaptor.capture(), exceptionMessageCaptor.capture()); + assertThat(cpComponentNameCaptor.getValue()) + .isSameInstanceAs(CREDENTIAL_PROVIDER_COMPONENT); + assertThat(exceptionTypeCaptor.getValue()) + .isEqualTo(GetCredentialException.TYPE_USER_CANCELED); + } + + @Test + public void testOnUiEntrySelected_correctEntryKeyPendingIntentResponseExists_succeeds() { + final ArgumentCaptor<GetCredentialResponse> getCredentialResponseCaptor = + ArgumentCaptor.forClass(GetCredentialResponse.class); + final ArgumentCaptor<ComponentName> cpComponentNameCaptor = + ArgumentCaptor.forClass(ComponentName.class); + final ArgumentCaptor<ProviderSession.Status> statusCaptor = + ArgumentCaptor.forClass(ProviderSession.Status.class); + mProviderRegistryGetSession.invokeSession(); + GetCredentialProviderData providerData = (GetCredentialProviderData) + mProviderRegistryGetSession.prepareUiData(); + final Intent intent = new Intent(); + final GetCredentialResponse response = + new GetCredentialResponse(new Credential(CREDENTIAL_TYPE, new Bundle())); + intent.putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_RESPONSE, response); + String entryKey = providerData.getCredentialEntries().get(0).getSubkey(); + final ProviderPendingIntentResponse providerPendingIntentResponse = new + ProviderPendingIntentResponse(Activity.RESULT_OK, intent); + + mProviderRegistryGetSession.onUiEntrySelected( + ProviderRegistryGetSession.CREDENTIAL_ENTRY_KEY, + entryKey, providerPendingIntentResponse); + + verify(mGetRequestSession).onProviderStatusChanged(statusCaptor.capture(), + cpComponentNameCaptor.capture()); + assertThat(statusCaptor.getValue()).isEqualTo(ProviderSession.Status.CREDENTIALS_RECEIVED); + verify(mGetRequestSession).onFinalResponseReceived(cpComponentNameCaptor.capture(), + getCredentialResponseCaptor.capture()); + assertThat(cpComponentNameCaptor.getValue()) + .isSameInstanceAs(CREDENTIAL_PROVIDER_COMPONENT); + assertThat(getCredentialResponseCaptor.getValue()).isSameInstanceAs(response); + } + + private static Slice createSlice() { + return new Slice.Builder(Uri.EMPTY, new SliceSpec("", 0)).build(); + } + + private static CallingAppInfo createCallingAppInfo() throws CertificateException { + return new CallingAppInfo(CALLING_PACKAGE_NAME, + new SigningInfo( + new SigningDetails(new Signature[]{}, 0, + null))); + } +} |