summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Omer Ozer <omerozer@google.com> 2023-03-08 19:00:12 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-03-08 19:00:12 +0000
commite9a096d2a79d32f04118333d3fd111da33d91175 (patch)
tree157ddc763a7dca421dcaebcad9e54208c1ce6656
parent4a3be7ee9703bfb2974945e16e98e37101e69bd8 (diff)
parent5e2914e8f8d45fd99952b669fb6190d31e62209e (diff)
Merge "Adding tests for ProviderRegistryGetSession" into udc-dev
-rw-r--r--core/java/android/service/credentials/CredentialProviderInfoFactory.java47
-rw-r--r--services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java22
-rw-r--r--services/credentials/java/com/android/server/credentials/CredentialManagerService.java22
-rw-r--r--services/credentials/java/com/android/server/credentials/GetRequestSession.java2
-rw-r--r--services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java19
-rw-r--r--services/credentials/java/com/android/server/credentials/ProviderSession.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/credentials/ProviderRegistryGetSessionTest.java341
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)));
+ }
+}