aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBecca Hughes <beccahughes@google.com>2023-07-05 19:46:37 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2023-07-05 19:46:37 +0000
commit08006ea049db1221bbe3da19b08b8bf0f65a76af (patch)
tree1e3b8e746bb08495df17ab5de7f80802238b8985
parent60ba3de45074eabd8a32fc7dff2269cbd2bea983 (diff)
parentf0d0958c3fb518e5a4b48db0bf4c1db0953c7430 (diff)
downloadsupport-08006ea049db1221bbe3da19b08b8bf0f65a76af.tar.gz
Merge "Use fragments internally for play services" into androidx-main
-rw-r--r--credentials/credentials-play-services-auth/src/androidTest/AndroidManifest.xml4
-rw-r--r--credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/TestCredentialsFragmentActivity.kt28
-rw-r--r--credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerJavaTest.java70
-rw-r--r--credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerTest.kt61
-rw-r--r--credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpassword/CredentialProviderCreatePasswordControllerJavaTest.java61
-rw-r--r--credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpassword/CredentialProviderCreatePasswordControllerTest.kt55
-rw-r--r--credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpublickeycredential/CredentialProviderCreatePublicKeyCredentialControllerJavaTest.java300
-rw-r--r--credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpublickeycredential/CredentialProviderCreatePublicKeyCredentialControllerTest.kt83
-rw-r--r--credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/CredentialProviderFragment.kt93
-rw-r--r--credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/GmsCoreUtils.kt266
-rw-r--r--credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/HiddenActivity.kt316
-rw-r--r--credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/CredentialProviderBeginSignInController.kt16
-rw-r--r--credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePassword/CredentialProviderCreatePasswordController.kt17
-rw-r--r--credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePublicKeyCredential/CredentialProviderCreatePublicKeyCredentialController.kt15
14 files changed, 948 insertions, 437 deletions
diff --git a/credentials/credentials-play-services-auth/src/androidTest/AndroidManifest.xml b/credentials/credentials-play-services-auth/src/androidTest/AndroidManifest.xml
index d7b0e91c4a1..73badf78bfb 100644
--- a/credentials/credentials-play-services-auth/src/androidTest/AndroidManifest.xml
+++ b/credentials/credentials-play-services-auth/src/androidTest/AndroidManifest.xml
@@ -21,5 +21,9 @@
android:name="androidx.credentials.playservices.TestCredentialsActivity"
android:exported="false"
/>
+ <activity
+ android:name="androidx.credentials.playservices.TestCredentialsFragmentActivity"
+ android:exported="false"
+ />
</application>
</manifest> \ No newline at end of file
diff --git a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/TestCredentialsFragmentActivity.kt b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/TestCredentialsFragmentActivity.kt
new file mode 100644
index 00000000000..f7ad106061f
--- /dev/null
+++ b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/TestCredentialsFragmentActivity.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright 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 androidx.credentials.playservices
+
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.fragment.app.FragmentActivity
+
+/**
+ * This is a test activity used by the Robolectric Activity Scenario tests. It acts as a calling
+ * activity in our test cases. This activity uses fragments.
+ */
+@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1)
+class TestCredentialsFragmentActivity : FragmentActivity()
diff --git a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerJavaTest.java b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerJavaTest.java
index e4cdddae662..acbfe57aee6 100644
--- a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerJavaTest.java
+++ b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerJavaTest.java
@@ -20,12 +20,14 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
+import android.app.Activity;
+import android.os.Build;
+
import androidx.credentials.GetCredentialRequest;
import androidx.credentials.GetPasswordOption;
import androidx.credentials.playservices.TestCredentialsActivity;
import androidx.credentials.playservices.controllers.BeginSignIn.CredentialProviderBeginSignInController;
import androidx.test.core.app.ActivityScenario;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.google.android.gms.auth.api.identity.BeginSignInRequest;
@@ -33,19 +35,56 @@ import com.google.android.libraries.identity.googleid.GetGoogleIdOption;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
import java.util.HashSet;
import java.util.List;
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
@SmallTest
@SuppressWarnings("deprecation")
public class CredentialProviderBeginSignInControllerJavaTest {
+
+ private final boolean mUseFragmentActivity;
+
+ @Parameterized.Parameters
+ public static Object[] data() {
+ return new Object[] {true, false};
+ }
+
+ public CredentialProviderBeginSignInControllerJavaTest(final boolean useFragmentActivity)
+ throws Throwable {
+ mUseFragmentActivity = useFragmentActivity;
+ }
+
+ interface TestActivityListener {
+ void onActivity(Activity a);
+ }
+
+ private void launchTestActivity(TestActivityListener listener) {
+ if (mUseFragmentActivity && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
+ ActivityScenario<androidx.credentials.playservices.TestCredentialsFragmentActivity>
+ activityScenario =
+ ActivityScenario.launch(
+ androidx.credentials.playservices
+ .TestCredentialsFragmentActivity.class);
+ activityScenario.onActivity(
+ activity -> {
+ listener.onActivity((Activity) activity);
+ });
+ } else {
+ ActivityScenario<TestCredentialsActivity> activityScenario =
+ ActivityScenario.launch(TestCredentialsActivity.class);
+ activityScenario.onActivity(
+ activity -> {
+ listener.onActivity((Activity) activity);
+ });
+ }
+ }
+
@Test
public void convertRequestToPlayServices_setPasswordOptionRequestAndFalseAutoSelect_success() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
- activityScenario.onActivity(
+ launchTestActivity(
activity -> {
BeginSignInRequest actualResponse =
CredentialProviderBeginSignInController.getInstance(activity)
@@ -60,9 +99,7 @@ public class CredentialProviderBeginSignInControllerJavaTest {
@Test
public void convertRequestToPlayServices_setPasswordOptionRequestAndTrueAutoSelect_success() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
- activityScenario.onActivity(
+ launchTestActivity(
activity -> {
BeginSignInRequest actualResponse =
CredentialProviderBeginSignInController.getInstance(activity)
@@ -79,9 +116,7 @@ public class CredentialProviderBeginSignInControllerJavaTest {
@Test
public void convertRequestToPlayServices_nullRequest_throws() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
- activityScenario.onActivity(
+ launchTestActivity(
activity -> {
assertThrows(
"null get credential request must throw exception",
@@ -94,9 +129,7 @@ public class CredentialProviderBeginSignInControllerJavaTest {
@Test
public void convertResponseToCredentialManager_nullRequest_throws() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
- activityScenario.onActivity(
+ launchTestActivity(
activity -> {
assertThrows(
"null sign in credential response must throw exception",
@@ -109,9 +142,6 @@ public class CredentialProviderBeginSignInControllerJavaTest {
@Test
public void convertRequestToPlayServices_setGoogleIdOptionRequestAndTrueAutoSelect_success() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
-
GetGoogleIdOption option =
new GetGoogleIdOption.Builder()
.setServerClientId("server_client_id")
@@ -122,7 +152,7 @@ public class CredentialProviderBeginSignInControllerJavaTest {
.setAutoSelectEnabled(true)
.build();
- activityScenario.onActivity(
+ launchTestActivity(
activity -> {
BeginSignInRequest actualRequest =
CredentialProviderBeginSignInController.getInstance(activity)
@@ -151,9 +181,7 @@ public class CredentialProviderBeginSignInControllerJavaTest {
@Test
public void duplicateGetInstance_shouldBeEqual() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
- activityScenario.onActivity(
+ launchTestActivity(
activity -> {
CredentialProviderBeginSignInController firstInstance =
CredentialProviderBeginSignInController.getInstance(activity);
diff --git a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerTest.kt b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerTest.kt
index 98ba9e3bdf8..dc5ea88631e 100644
--- a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerTest.kt
+++ b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerTest.kt
@@ -16,32 +16,55 @@
package androidx.credentials.playservices.beginsignin
+import android.app.Activity
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.credentials.GetCredentialRequest
import androidx.credentials.GetPasswordOption
import androidx.credentials.playservices.TestCredentialsActivity
+import androidx.credentials.playservices.TestCredentialsFragmentActivity
import androidx.credentials.playservices.controllers.BeginSignIn.CredentialProviderBeginSignInController.Companion.getInstance
import androidx.test.core.app.ActivityScenario
-import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.google.android.libraries.identity.googleid.GetGoogleIdOption
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
-@RunWith(AndroidJUnit4::class)
+@RunWith(Parameterized::class)
@SmallTest
@Suppress("deprecation")
@RequiresApi(api = Build.VERSION_CODES.O)
-class CredentialProviderBeginSignInControllerTest {
+class CredentialProviderBeginSignInControllerTest(val useFragmentActivity: Boolean) {
+
+ companion object {
+ @JvmStatic
+ @Parameterized.Parameters(name = "{0}")
+ fun initParameters() = listOf(true, false)
+ }
+
+ private fun launchTestActivity(callback: (activity: Activity) -> Unit) {
+ if (useFragmentActivity && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
+ var activityScenario =
+ ActivityScenario.launch(
+ androidx.credentials.playservices
+ .TestCredentialsFragmentActivity::class.java)
+ activityScenario.onActivity { activity: Activity ->
+ callback.invoke(activity)
+ }
+ } else {
+ var activityScenario = ActivityScenario.launch(TestCredentialsActivity::class.java)
+ activityScenario.onActivity { activity: Activity ->
+ callback.invoke(activity)
+ }
+ }
+ }
+
@Test
fun convertRequestToPlayServices_setPasswordOptionRequestAndFalseAutoSelect_success() {
- val activityScenario = ActivityScenario.launch(
- TestCredentialsActivity::class.java
- )
- activityScenario.onActivity { activity: TestCredentialsActivity? ->
- val actualResponse = getInstance(activity!!)
+ launchTestActivity { activity: Activity ->
+ val actualResponse = getInstance(activity)
.convertRequestToPlayServices(
GetCredentialRequest(
listOf(
@@ -58,11 +81,8 @@ class CredentialProviderBeginSignInControllerTest {
@Test
fun convertRequestToPlayServices_setPasswordOptionRequestAndTrueAutoSelect_success() {
- val activityScenario = ActivityScenario.launch(
- TestCredentialsActivity::class.java
- )
- activityScenario.onActivity { activity: TestCredentialsActivity? ->
- val actualResponse = getInstance(activity!!)
+ launchTestActivity { activity: Activity ->
+ val actualResponse = getInstance(activity)
.convertRequestToPlayServices(
GetCredentialRequest(
listOf(
@@ -79,10 +99,6 @@ class CredentialProviderBeginSignInControllerTest {
@Test
fun convertRequestToPlayServices_setGoogleIdOptionRequest_success() {
- val activityScenario = ActivityScenario.launch(
- TestCredentialsActivity::class.java
- )
-
val option = GetGoogleIdOption.Builder()
.setServerClientId("server_client_id")
.setNonce("nonce")
@@ -92,8 +108,8 @@ class CredentialProviderBeginSignInControllerTest {
.setAutoSelectEnabled(true)
.build()
- activityScenario.onActivity { activity: TestCredentialsActivity? ->
- val actualRequest = getInstance(activity!!)
+ launchTestActivity { activity: Activity ->
+ val actualRequest = getInstance(activity)
.convertRequestToPlayServices(
GetCredentialRequest(
listOf(
@@ -120,12 +136,9 @@ class CredentialProviderBeginSignInControllerTest {
@Test
fun duplicateGetInstance_shouldBeEqual() {
- val activityScenario = ActivityScenario.launch(
- TestCredentialsActivity::class.java
- )
- activityScenario.onActivity { activity: TestCredentialsActivity? ->
+ launchTestActivity { activity: Activity ->
- val firstInstance = getInstance(activity!!)
+ val firstInstance = getInstance(activity)
val secondInstance = getInstance(activity)
assertThat(firstInstance).isEqualTo(secondInstance)
}
diff --git a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpassword/CredentialProviderCreatePasswordControllerJavaTest.java b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpassword/CredentialProviderCreatePasswordControllerJavaTest.java
index 00b86bae5b0..f0d5a850d1e 100644
--- a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpassword/CredentialProviderCreatePasswordControllerJavaTest.java
+++ b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpassword/CredentialProviderCreatePasswordControllerJavaTest.java
@@ -20,6 +20,8 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
+import android.app.Activity;
+import android.os.Build;
import android.os.Bundle;
import androidx.credentials.CreateCredentialResponse;
@@ -29,7 +31,6 @@ import androidx.credentials.playservices.TestCredentialsActivity;
import androidx.credentials.playservices.TestUtils;
import androidx.credentials.playservices.controllers.CreatePassword.CredentialProviderCreatePasswordController;
import androidx.test.core.app.ActivityScenario;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.google.android.gms.auth.api.identity.SignInPassword;
@@ -38,17 +39,53 @@ import kotlin.Unit;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
@SmallTest
public class CredentialProviderCreatePasswordControllerJavaTest {
+ private final boolean mUseFragmentActivity;
+
+ @Parameterized.Parameters
+ public static Object[] data() {
+ return new Object[] {true, false};
+ }
+
+ public CredentialProviderCreatePasswordControllerJavaTest(final boolean useFragmentActivity)
+ throws Throwable {
+ mUseFragmentActivity = useFragmentActivity;
+ }
+
+ interface TestActivityListener {
+ void onActivity(Activity a);
+ }
+
+ private void launchTestActivity(TestActivityListener listener) {
+ if (mUseFragmentActivity && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
+ ActivityScenario<androidx.credentials.playservices.TestCredentialsFragmentActivity>
+ activityScenario =
+ ActivityScenario.launch(
+ androidx.credentials.playservices
+ .TestCredentialsFragmentActivity.class);
+ activityScenario.onActivity(
+ activity -> {
+ listener.onActivity((Activity) activity);
+ });
+ } else {
+ ActivityScenario<TestCredentialsActivity> activityScenario =
+ ActivityScenario.launch(TestCredentialsActivity.class);
+ activityScenario.onActivity(
+ activity -> {
+ listener.onActivity((Activity) activity);
+ });
+ }
+ }
+
@Test
public void convertResponseToCredentialManager_unitInput_success() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
String expectedResponseType = new CreatePasswordResponse().getType();
- activityScenario.onActivity(
+ launchTestActivity(
activity -> {
CreateCredentialResponse actualResponse =
CredentialProviderCreatePasswordController.getInstance(activity)
@@ -62,11 +99,9 @@ public class CredentialProviderCreatePasswordControllerJavaTest {
@Test
public void convertRequestToPlayServices_createPasswordRequest_success() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
String expectedId = "LM";
String expectedPassword = "SodaButton";
- activityScenario.onActivity(
+ launchTestActivity(
activity -> {
SignInPassword actualRequest =
CredentialProviderCreatePasswordController.getInstance(activity)
@@ -83,7 +118,7 @@ public class CredentialProviderCreatePasswordControllerJavaTest {
public void convertRequestToPlayServices_nullRequest_throws() {
ActivityScenario<TestCredentialsActivity> activityScenario =
ActivityScenario.launch(TestCredentialsActivity.class);
- activityScenario.onActivity(
+ launchTestActivity(
activity -> {
assertThrows(
"null create password request must throw exception",
@@ -97,9 +132,7 @@ public class CredentialProviderCreatePasswordControllerJavaTest {
@Test
public void convertResponseToCredentialManager_nullRequest_throws() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
- activityScenario.onActivity(
+ launchTestActivity(
activity -> {
assertThrows(
"null unit response must throw exception",
@@ -112,9 +145,7 @@ public class CredentialProviderCreatePasswordControllerJavaTest {
@Test
public void duplicateGetInstance_shouldBeEqual() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
- activityScenario.onActivity(
+ launchTestActivity(
activity -> {
CredentialProviderCreatePasswordController firstInstance =
CredentialProviderCreatePasswordController.getInstance(activity);
diff --git a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpassword/CredentialProviderCreatePasswordControllerTest.kt b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpassword/CredentialProviderCreatePasswordControllerTest.kt
index 128c9702724..5afb279ac18 100644
--- a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpassword/CredentialProviderCreatePasswordControllerTest.kt
+++ b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpassword/CredentialProviderCreatePasswordControllerTest.kt
@@ -16,31 +16,56 @@
package androidx.credentials.playservices.createpassword
+import android.app.Activity
+import android.os.Build
import android.os.Bundle
+import androidx.annotation.DoNotInline
import androidx.credentials.CreatePasswordRequest
import androidx.credentials.CreatePasswordResponse
import androidx.credentials.playservices.TestCredentialsActivity
import androidx.credentials.playservices.TestUtils.Companion.equals
import androidx.credentials.playservices.controllers.CreatePassword.CredentialProviderCreatePasswordController.Companion.getInstance
import androidx.test.core.app.ActivityScenario
-import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
-@RunWith(AndroidJUnit4::class)
+@RunWith(Parameterized::class)
@SmallTest
-class CredentialProviderCreatePasswordControllerTest {
+class CredentialProviderCreatePasswordControllerTest(val useFragmentActivity: Boolean) {
+
+ companion object {
+ @JvmStatic
+ @Parameterized.Parameters(name = "{0}")
+ fun initParameters() = listOf(true, false)
+ }
+
+ @DoNotInline
+ private fun launchTestActivity(callback: (activity: Activity) -> Unit) {
+ if (useFragmentActivity && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
+ var activityScenario =
+ ActivityScenario.launch(
+ androidx.credentials.playservices
+ .TestCredentialsFragmentActivity::class.java)
+ activityScenario.onActivity { activity: Activity ->
+ callback.invoke(activity)
+ }
+ } else {
+ var activityScenario = ActivityScenario.launch(TestCredentialsActivity::class.java)
+ activityScenario.onActivity { activity: Activity ->
+ callback.invoke(activity)
+ }
+ }
+ }
+
@Test
fun convertResponseToCredentialManager_unitInput_success() {
- val activityScenario = ActivityScenario.launch(
- TestCredentialsActivity::class.java
- )
val expectedResponseType = CreatePasswordResponse().type
- activityScenario.onActivity { activity: TestCredentialsActivity? ->
+ launchTestActivity { activity: Activity ->
- val actualResponse = getInstance(activity!!)
+ val actualResponse = getInstance(activity)
.convertResponseToCredentialManager(Unit)
assertThat(actualResponse.type)
@@ -51,14 +76,11 @@ class CredentialProviderCreatePasswordControllerTest {
@Test
fun convertRequestToPlayServices_createPasswordRequest_success() {
- val activityScenario = ActivityScenario.launch(
- TestCredentialsActivity::class.java
- )
val expectedId = "LM"
val expectedPassword = "SodaButton"
- activityScenario.onActivity { activity: TestCredentialsActivity? ->
+ launchTestActivity { activity: Activity ->
- val actualRequest = getInstance(activity!!)
+ val actualRequest = getInstance(activity)
.convertRequestToPlayServices(CreatePasswordRequest(
expectedId, expectedPassword)).signInPassword
@@ -70,12 +92,9 @@ class CredentialProviderCreatePasswordControllerTest {
@Test
fun duplicateGetInstance_shouldBeEqual() {
- val activityScenario = ActivityScenario.launch(
- TestCredentialsActivity::class.java
- )
- activityScenario.onActivity { activity: TestCredentialsActivity? ->
+ launchTestActivity { activity: Activity ->
- val firstInstance = getInstance(activity!!)
+ val firstInstance = getInstance(activity)
val secondInstance = getInstance(activity)
assertThat(firstInstance).isEqualTo(secondInstance)
}
diff --git a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpublickeycredential/CredentialProviderCreatePublicKeyCredentialControllerJavaTest.java b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpublickeycredential/CredentialProviderCreatePublicKeyCredentialControllerJavaTest.java
index 8fba8ffa601..5e92ef88a2f 100644
--- a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpublickeycredential/CredentialProviderCreatePublicKeyCredentialControllerJavaTest.java
+++ b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpublickeycredential/CredentialProviderCreatePublicKeyCredentialControllerJavaTest.java
@@ -33,12 +33,14 @@ import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertThrows;
+import android.app.Activity;
+import android.os.Build;
+
import androidx.credentials.CreatePublicKeyCredentialRequest;
import androidx.credentials.playservices.TestCredentialsActivity;
import androidx.credentials.playservices.TestUtils;
import androidx.credentials.playservices.controllers.CreatePublicKeyCredential.CredentialProviderCreatePublicKeyCredentialController;
import androidx.test.core.app.ActivityScenario;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialCreationOptions;
@@ -47,157 +49,209 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
@SmallTest
public class CredentialProviderCreatePublicKeyCredentialControllerJavaTest {
+
+ private final boolean mUseFragmentActivity;
+
+ @Parameterized.Parameters
+ public static Object[] data() {
+ return new Object[] {true, false};
+ }
+
+ public CredentialProviderCreatePublicKeyCredentialControllerJavaTest(
+ final boolean useFragmentActivity) throws Throwable {
+ mUseFragmentActivity = useFragmentActivity;
+ }
+
+ interface TestActivityListener {
+ void onActivity(Activity a);
+ }
+
+ private void launchTestActivity(TestActivityListener listener) {
+ if (mUseFragmentActivity && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
+ ActivityScenario<androidx.credentials.playservices.TestCredentialsFragmentActivity>
+ activityScenario =
+ ActivityScenario.launch(
+ androidx.credentials.playservices
+ .TestCredentialsFragmentActivity.class);
+ activityScenario.onActivity(
+ activity -> {
+ listener.onActivity((Activity) activity);
+ });
+ } else {
+ ActivityScenario<TestCredentialsActivity> activityScenario =
+ ActivityScenario.launch(TestCredentialsActivity.class);
+ activityScenario.onActivity(
+ activity -> {
+ listener.onActivity((Activity) activity);
+ });
+ }
+ }
+
+ private PublicKeyCredentialCreationOptions convertRequestToPlayServices(
+ Activity activity, String type) {
+ CreatePublicKeyCredentialRequest pubKeyRequest = new CreatePublicKeyCredentialRequest(type);
+ return CredentialProviderCreatePublicKeyCredentialController.getInstance(activity)
+ .convertRequestToPlayServices(pubKeyRequest);
+ }
+
@Test
- public void
- convertRequestToPlayServices_correctRequiredOnlyRequest_success() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
- activityScenario.onActivity(activity -> {
- try {
- JSONObject expectedJson = new JSONObject(
- MAIN_CREATE_JSON_ALL_REQUIRED_FIELDS_PRESENT);
-
- PublicKeyCredentialCreationOptions actualResponse =
- CredentialProviderCreatePublicKeyCredentialController.getInstance(activity)
- .convertRequestToPlayServices(
- new CreatePublicKeyCredentialRequest(
- MAIN_CREATE_JSON_ALL_REQUIRED_FIELDS_PRESENT));
- JSONObject actualJson = createJsonObjectFromPublicKeyCredentialCreationOptions(
+ public void convertRequestToPlayServices_correctRequiredOnlyRequest_success() {
+ launchTestActivity(
+ activity -> {
+ try {
+ JSONObject expectedJson =
+ new JSONObject(MAIN_CREATE_JSON_ALL_REQUIRED_FIELDS_PRESENT);
+
+ PublicKeyCredentialCreationOptions actualResponse =
+ convertRequestToPlayServices(
+ activity,
+ MAIN_CREATE_JSON_ALL_REQUIRED_FIELDS_PRESENT);
+ JSONObject actualJson =
+ createJsonObjectFromPublicKeyCredentialCreationOptions(
actualResponse);
- JSONObject requiredKeys = new JSONObject(ALL_REQUIRED_FIELDS_SIGNATURE);
-
- assertThat(TestUtils.Companion.isSubsetJson(expectedJson, actualJson,
- requiredKeys)).isTrue();
- // TODO("Add remaining tests in detail after discussing ideal form")
- } catch (JSONException e) {
- throw new RuntimeException(e);
- }
- });
+ JSONObject requiredKeys = new JSONObject(ALL_REQUIRED_FIELDS_SIGNATURE);
+
+ assertThat(
+ TestUtils.Companion.isSubsetJson(
+ expectedJson, actualJson, requiredKeys))
+ .isTrue();
+ // TODO("Add remaining tests in detail after discussing ideal form")
+ } catch (JSONException e) {
+ throw new RuntimeException(e);
+ }
+ });
}
@Test
public void convertRequestToPlayServices_correctRequiredAndOptionalRequest_success() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
- activityScenario.onActivity(activity -> {
- try {
- JSONObject expectedJson = new JSONObject(
- MAIN_CREATE_JSON_ALL_REQUIRED_AND_OPTIONAL_FIELDS_PRESENT);
-
- PublicKeyCredentialCreationOptions actualResponse =
- CredentialProviderCreatePublicKeyCredentialController.getInstance(activity)
- .convertRequestToPlayServices(new CreatePublicKeyCredentialRequest(
- MAIN_CREATE_JSON_ALL_REQUIRED_AND_OPTIONAL_FIELDS_PRESENT));
- JSONObject actualJson =
- createJsonObjectFromPublicKeyCredentialCreationOptions(
+ launchTestActivity(
+ activity -> {
+ try {
+ JSONObject expectedJson =
+ new JSONObject(
+ MAIN_CREATE_JSON_ALL_REQUIRED_AND_OPTIONAL_FIELDS_PRESENT);
+
+ PublicKeyCredentialCreationOptions actualResponse =
+ convertRequestToPlayServices(
+ activity,
+ MAIN_CREATE_JSON_ALL_REQUIRED_AND_OPTIONAL_FIELDS_PRESENT);
+ JSONObject actualJson =
+ createJsonObjectFromPublicKeyCredentialCreationOptions(
actualResponse);
- JSONObject requiredKeys = new JSONObject(ALL_REQUIRED_AND_OPTIONAL_SIGNATURE);
-
- assertThat(TestUtils.Companion.isSubsetJson(expectedJson, actualJson,
- requiredKeys)).isTrue();
- // TODO("Add remaining tests in detail after discussing ideal form")
- } catch (JSONException e) {
- throw new RuntimeException(e);
- }
- });
+ JSONObject requiredKeys =
+ new JSONObject(ALL_REQUIRED_AND_OPTIONAL_SIGNATURE);
+
+ assertThat(
+ TestUtils.Companion.isSubsetJson(
+ expectedJson, actualJson, requiredKeys))
+ .isTrue();
+ // TODO("Add remaining tests in detail after discussing ideal form")
+ } catch (JSONException e) {
+ throw new RuntimeException(e);
+ }
+ });
}
+
@Test
public void convertRequestToPlayServices_missingRequired_throws() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
- activityScenario.onActivity(activity -> {
- try {
- CredentialProviderCreatePublicKeyCredentialController
- .getInstance(activity)
- .convertRequestToPlayServices(
- new CreatePublicKeyCredentialRequest(
- MAIN_CREATE_JSON_MISSING_REQUIRED_FIELD));
-
- // Should not reach here.
- assertWithMessage("Exception should be thrown").that(true).isFalse();
- } catch (Exception e) {
- assertThat(e.getMessage().contains("No value for id")).isTrue();
- assertThat(e.getClass().getName().contains("JSONException")).isTrue();
- }
- });
+ launchTestActivity(
+ activity -> {
+ try {
+ PublicKeyCredentialCreationOptions actualResponse =
+ convertRequestToPlayServices(
+ activity,
+ MAIN_CREATE_JSON_ALL_REQUIRED_FIELDS_PRESENT);
+
+ CreatePublicKeyCredentialRequest pubKeyRequest =
+ new CreatePublicKeyCredentialRequest(
+ MAIN_CREATE_JSON_ALL_REQUIRED_FIELDS_PRESENT);
+ CredentialProviderCreatePublicKeyCredentialController.getInstance(activity)
+ .convertRequestToPlayServices(
+ new CreatePublicKeyCredentialRequest(
+ MAIN_CREATE_JSON_MISSING_REQUIRED_FIELD));
+
+ // Should not reach here.
+ assertWithMessage("Exception should be thrown").that(true).isFalse();
+ } catch (Exception e) {
+ assertThat(e.getMessage().contains("No value for id")).isTrue();
+ assertThat(e.getClass().getName().contains("JSONException")).isTrue();
+ }
+ });
}
@Test
public void convertRequestToPlayServices_emptyRequired_throws() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
- activityScenario.onActivity(activity -> {
-
- assertThrows("Expected bad required json to throw",
- JSONException.class,
- () -> CredentialProviderCreatePublicKeyCredentialController
- .getInstance(activity).convertRequestToPlayServices(
- new CreatePublicKeyCredentialRequest(
- MAIN_CREATE_JSON_REQUIRED_FIELD_EMPTY)));
- });
+ launchTestActivity(
+ activity -> {
+ assertThrows(
+ "Expected bad required json to throw",
+ JSONException.class,
+ () ->
+ convertRequestToPlayServices(
+ activity,
+ MAIN_CREATE_JSON_REQUIRED_FIELD_EMPTY));
+ });
}
@Test
public void convertRequestToPlayServices_missingOptionalRequired_throws() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
- activityScenario.onActivity(activity -> {
-
- assertThrows("Expected bad required json to throw",
- JSONException.class,
- () -> CredentialProviderCreatePublicKeyCredentialController
- .getInstance(activity)
- .convertRequestToPlayServices(
- new CreatePublicKeyCredentialRequest(
- OPTIONAL_FIELD_MISSING_REQUIRED_SUBFIELD)));
- });
+ launchTestActivity(
+ activity -> {
+ assertThrows(
+ "Expected bad required json to throw",
+ JSONException.class,
+ () ->
+ convertRequestToPlayServices(
+ activity,
+ OPTIONAL_FIELD_MISSING_REQUIRED_SUBFIELD));
+ });
}
@Test
public void convertRequestToPlayServices_emptyOptionalRequired_throws() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
- activityScenario.onActivity(activity -> {
-
- assertThrows("Expected bad required json to throw",
- JSONException.class,
- () -> CredentialProviderCreatePublicKeyCredentialController
- .getInstance(activity)
- .convertRequestToPlayServices(
- new CreatePublicKeyCredentialRequest(
- OPTIONAL_FIELD_WITH_EMPTY_REQUIRED_SUBFIELD)));
- });
+ launchTestActivity(
+ activity -> {
+ assertThrows(
+ "Expected bad required json to throw",
+ JSONException.class,
+ () ->
+ convertRequestToPlayServices(
+ activity,
+ OPTIONAL_FIELD_WITH_EMPTY_REQUIRED_SUBFIELD));
+ });
}
@Test
public void convertRequestToPlayServices_missingOptionalNotRequired_success() {
- ActivityScenario<TestCredentialsActivity> activityScenario =
- ActivityScenario.launch(TestCredentialsActivity.class);
- activityScenario.onActivity(activity -> {
- try {
- JSONObject expectedJson = new JSONObject(
- OPTIONAL_FIELD_MISSING_OPTIONAL_SUBFIELD);
-
- PublicKeyCredentialCreationOptions actualResponse =
- CredentialProviderCreatePublicKeyCredentialController.getInstance(activity)
- .convertRequestToPlayServices(
- new CreatePublicKeyCredentialRequest(
- OPTIONAL_FIELD_MISSING_OPTIONAL_SUBFIELD));
- JSONObject actualJson = createJsonObjectFromPublicKeyCredentialCreationOptions(
+ launchTestActivity(
+ activity -> {
+ try {
+ JSONObject expectedJson =
+ new JSONObject(OPTIONAL_FIELD_MISSING_OPTIONAL_SUBFIELD);
+
+ PublicKeyCredentialCreationOptions actualResponse =
+ convertRequestToPlayServices(
+ activity,
+ OPTIONAL_FIELD_MISSING_OPTIONAL_SUBFIELD);
+ JSONObject actualJson =
+ createJsonObjectFromPublicKeyCredentialCreationOptions(
actualResponse);
- JSONObject requiredKeys = new
- JSONObject(OPTIONAL_FIELD_MISSING_OPTIONAL_SUBFIELD_SIGNATURE);
-
- assertThat(TestUtils.Companion.isSubsetJson(expectedJson, actualJson,
- requiredKeys)).isTrue();
- // TODO("Add remaining tests in detail after discussing ideal form")
- } catch (JSONException e) {
- throw new RuntimeException(e);
- }
- });
+ JSONObject requiredKeys =
+ new JSONObject(OPTIONAL_FIELD_MISSING_OPTIONAL_SUBFIELD_SIGNATURE);
+
+ assertThat(
+ TestUtils.Companion.isSubsetJson(
+ expectedJson, actualJson, requiredKeys))
+ .isTrue();
+ // TODO("Add remaining tests in detail after discussing ideal form")
+ } catch (JSONException e) {
+ throw new RuntimeException(e);
+ }
+ });
}
}
diff --git a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpublickeycredential/CredentialProviderCreatePublicKeyCredentialControllerTest.kt b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpublickeycredential/CredentialProviderCreatePublicKeyCredentialControllerTest.kt
index c33a9686cd9..e06486ae9b0 100644
--- a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpublickeycredential/CredentialProviderCreatePublicKeyCredentialControllerTest.kt
+++ b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpublickeycredential/CredentialProviderCreatePublicKeyCredentialControllerTest.kt
@@ -16,6 +16,9 @@
package androidx.credentials.playservices.createpublickeycredential
+import android.app.Activity
+import android.os.Build
+import androidx.annotation.DoNotInline
import androidx.credentials.CreatePublicKeyCredentialRequest
import androidx.credentials.playservices.TestCredentialsActivity
import androidx.credentials.playservices.TestUtils.Companion.isSubsetJson
@@ -32,7 +35,6 @@ import androidx.credentials.playservices.createkeycredential.CreatePublicKeyCred
import androidx.credentials.playservices.createkeycredential.CreatePublicKeyCredentialControllerTestUtils.Companion.OPTIONAL_FIELD_WITH_EMPTY_REQUIRED_SUBFIELD
import androidx.credentials.playservices.createkeycredential.CreatePublicKeyCredentialControllerTestUtils.Companion.createJsonObjectFromPublicKeyCredentialCreationOptions
import androidx.test.core.app.ActivityScenario
-import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
import org.json.JSONException
@@ -41,20 +43,43 @@ import org.junit.Assert
import org.junit.Test
import org.junit.function.ThrowingRunnable
import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
-@RunWith(AndroidJUnit4::class)
+@RunWith(Parameterized::class)
@SmallTest
-class CredentialProviderCreatePublicKeyCredentialControllerTest {
+class CredentialProviderCreatePublicKeyCredentialControllerTest(val useFragmentActivity: Boolean) {
+
+ companion object {
+ @JvmStatic
+ @Parameterized.Parameters(name = "{0}")
+ fun initParameters() = listOf(true, false)
+ }
+
+ @DoNotInline
+ private fun launchTestActivity(callback: (activity: Activity) -> Unit) {
+ if (useFragmentActivity && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
+ var activityScenario =
+ ActivityScenario.launch(
+ androidx.credentials.playservices
+ .TestCredentialsFragmentActivity::class.java)
+ activityScenario.onActivity { activity: Activity ->
+ callback.invoke(activity)
+ }
+ } else {
+ var activityScenario = ActivityScenario.launch(TestCredentialsActivity::class.java)
+ activityScenario.onActivity { activity: Activity ->
+ callback.invoke(activity)
+ }
+ }
+ }
+
@Test
fun convertRequestToPlayServices_correctRequiredOnlyRequest_success() {
- val activityScenario = ActivityScenario.launch(
- TestCredentialsActivity::class.java
- )
- activityScenario.onActivity { activity: TestCredentialsActivity? ->
+ launchTestActivity { activity: Activity ->
try {
val expectedJson = JSONObject(MAIN_CREATE_JSON_ALL_REQUIRED_FIELDS_PRESENT)
- val actualResponse = getInstance(activity!!).convertRequestToPlayServices(
+ val actualResponse = getInstance(activity).convertRequestToPlayServices(
CreatePublicKeyCredentialRequest(
MAIN_CREATE_JSON_ALL_REQUIRED_FIELDS_PRESENT))
val actualJson =
@@ -72,15 +97,12 @@ class CredentialProviderCreatePublicKeyCredentialControllerTest {
@Test
fun convertRequestToPlayServices_correctRequiredAndOptionalRequest_success() {
- val activityScenario = ActivityScenario.launch(
- TestCredentialsActivity::class.java
- )
- activityScenario.onActivity { activity: TestCredentialsActivity? ->
+ launchTestActivity { activity: Activity ->
try {
val expectedJson = JSONObject(
MAIN_CREATE_JSON_ALL_REQUIRED_AND_OPTIONAL_FIELDS_PRESENT)
- val actualResponse = getInstance(activity!!)
+ val actualResponse = getInstance(activity)
.convertRequestToPlayServices(CreatePublicKeyCredentialRequest(
MAIN_CREATE_JSON_ALL_REQUIRED_AND_OPTIONAL_FIELDS_PRESENT))
val actualJson =
@@ -98,16 +120,13 @@ class CredentialProviderCreatePublicKeyCredentialControllerTest {
@Test
fun convertRequestToPlayServices_missingRequired_throws() {
- val activityScenario = ActivityScenario.launch(
- TestCredentialsActivity::class.java
- )
- activityScenario.onActivity { activity: TestCredentialsActivity? ->
+ launchTestActivity { activity: Activity ->
Assert.assertThrows("Expected bad required json to throw",
JSONException::class.java,
ThrowingRunnable {
getInstance(
- activity!!
+ activity
).convertRequestToPlayServices(
CreatePublicKeyCredentialRequest(
MAIN_CREATE_JSON_MISSING_REQUIRED_FIELD
@@ -117,30 +136,24 @@ class CredentialProviderCreatePublicKeyCredentialControllerTest {
@Test
fun convertRequestToPlayServices_emptyRequired_throws() {
- val activityScenario = ActivityScenario.launch(
- TestCredentialsActivity::class.java
- )
- activityScenario.onActivity { activity: TestCredentialsActivity? ->
+ launchTestActivity { activity: Activity ->
Assert.assertThrows("Expected bad required json to throw",
JSONException::class.java,
- ThrowingRunnable { getInstance(activity!!
+ ThrowingRunnable { getInstance(activity
).convertRequestToPlayServices(CreatePublicKeyCredentialRequest(
MAIN_CREATE_JSON_REQUIRED_FIELD_EMPTY)) })
}
}
@Test
fun convertRequestToPlayServices_missingOptionalRequired_throws() {
- val activityScenario = ActivityScenario.launch(
- TestCredentialsActivity::class.java
- )
- activityScenario.onActivity { activity: TestCredentialsActivity? ->
+ launchTestActivity { activity: Activity ->
Assert.assertThrows("Expected bad required json to throw",
JSONException::class.java,
ThrowingRunnable {
getInstance(
- activity!!
+ activity
).convertRequestToPlayServices(
CreatePublicKeyCredentialRequest(
OPTIONAL_FIELD_MISSING_REQUIRED_SUBFIELD)) })
@@ -149,14 +162,11 @@ class CredentialProviderCreatePublicKeyCredentialControllerTest {
@Test
fun convertRequestToPlayServices_emptyOptionalRequired_throws() {
- val activityScenario = ActivityScenario.launch(
- TestCredentialsActivity::class.java
- )
- activityScenario.onActivity { activity: TestCredentialsActivity? ->
+ launchTestActivity { activity: Activity ->
Assert.assertThrows("Expected bad required json to throw",
JSONException::class.java,
- ThrowingRunnable { getInstance(activity!!).convertRequestToPlayServices(
+ ThrowingRunnable { getInstance(activity).convertRequestToPlayServices(
CreatePublicKeyCredentialRequest(
OPTIONAL_FIELD_WITH_EMPTY_REQUIRED_SUBFIELD)) })
}
@@ -164,15 +174,12 @@ class CredentialProviderCreatePublicKeyCredentialControllerTest {
@Test
fun convertRequestToPlayServices_missingOptionalNotRequired_success() {
- val activityScenario = ActivityScenario.launch(
- TestCredentialsActivity::class.java
- )
- activityScenario.onActivity { activity: TestCredentialsActivity? ->
+ launchTestActivity { activity: Activity ->
try {
val expectedJson = JSONObject(OPTIONAL_FIELD_MISSING_OPTIONAL_SUBFIELD)
val actualResponse =
- getInstance(activity!!)
+ getInstance(activity)
.convertRequestToPlayServices(
CreatePublicKeyCredentialRequest(
OPTIONAL_FIELD_MISSING_OPTIONAL_SUBFIELD))
diff --git a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/CredentialProviderFragment.kt b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/CredentialProviderFragment.kt
new file mode 100644
index 00000000000..2d7f1e9d32e
--- /dev/null
+++ b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/CredentialProviderFragment.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright 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 androidx.credentials.playservices
+
+import android.content.Intent
+import android.os.Bundle
+import android.os.ResultReceiver
+import androidx.annotation.RestrictTo
+import androidx.credentials.playservices.controllers.CredentialProviderBaseController
+import androidx.fragment.app.Fragment
+
+/** A fragment used if we are passed a fragment activity. */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+@Suppress("Deprecation")
+open class CredentialProviderFragment : Fragment() {
+
+ private var resultReceiver: ResultReceiver? = null
+ private var mWaitingForActivityResult = false
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ resultReceiver = getResultReceiver()
+ if (resultReceiver == null) {
+ return
+ }
+
+ restoreState(savedInstanceState)
+ if (mWaitingForActivityResult) {
+ return // Past call still active
+ }
+ }
+
+ private fun getResultReceiver(): ResultReceiver? {
+ if (getArguments() == null) {
+ return null
+ }
+
+ return getArguments()!!.getParcelable(CredentialProviderBaseController.RESULT_RECEIVER_TAG)
+ as? ResultReceiver
+ }
+
+ private fun restoreState(savedInstanceState: Bundle?) {
+ if (savedInstanceState != null) {
+ mWaitingForActivityResult = savedInstanceState.getBoolean(KEY_AWAITING_RESULT, false)
+ }
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ outState.putBoolean(KEY_AWAITING_RESULT, mWaitingForActivityResult)
+ super.onSaveInstanceState(outState)
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ val bundle = Bundle()
+ bundle.putBoolean(CredentialProviderBaseController.FAILURE_RESPONSE_TAG, false)
+ bundle.putInt(CredentialProviderBaseController.ACTIVITY_REQUEST_CODE_TAG, requestCode)
+ bundle.putParcelable(CredentialProviderBaseController.RESULT_DATA_TAG, data)
+ resultReceiver?.send(resultCode, bundle)
+ mWaitingForActivityResult = false
+ }
+
+ companion object {
+ private const val TAG = "CredentialProviderFragment"
+ private const val KEY_AWAITING_RESULT = "androidx.credentials.playservices.AWAITING_RESULT"
+
+ fun createFrom(resultReceiver: ResultReceiver): CredentialProviderFragment {
+ val f = CredentialProviderFragment()
+
+ // Supply index input as an argument.
+ val args = Bundle()
+ args.putParcelable(CredentialProviderBaseController.RESULT_RECEIVER_TAG, resultReceiver)
+ f.setArguments(args)
+
+ return f
+ }
+ }
+}
diff --git a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/GmsCoreUtils.kt b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/GmsCoreUtils.kt
new file mode 100644
index 00000000000..112599dfc76
--- /dev/null
+++ b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/GmsCoreUtils.kt
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2022 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 androidx.credentials.playservices
+
+import android.app.Activity
+import android.app.PendingIntent
+import android.content.IntentSender
+import android.os.Bundle
+import android.os.ResultReceiver
+import android.util.Log
+import androidx.annotation.RestrictTo
+import androidx.credentials.playservices.controllers.CredentialProviderBaseController
+import androidx.credentials.playservices.controllers.CredentialProviderBaseController.Companion.CREATE_INTERRUPTED
+import androidx.credentials.playservices.controllers.CredentialProviderBaseController.Companion.CREATE_UNKNOWN
+import androidx.credentials.playservices.controllers.CredentialProviderBaseController.Companion.GET_INTERRUPTED
+import androidx.credentials.playservices.controllers.CredentialProviderBaseController.Companion.GET_NO_CREDENTIALS
+import androidx.credentials.playservices.controllers.CredentialProviderBaseController.Companion.GET_UNKNOWN
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
+import com.google.android.gms.auth.api.identity.BeginSignInRequest
+import com.google.android.gms.auth.api.identity.CredentialSavingClient
+import com.google.android.gms.auth.api.identity.SavePasswordRequest
+import com.google.android.gms.auth.api.identity.SignInClient
+import com.google.android.gms.common.api.ApiException
+import com.google.android.gms.fido.fido2.Fido2ApiClient
+import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialCreationOptions
+
+/** A util class for interacting with GmsCore. */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+@Suppress("Deprecation", "ForbiddenSuperClass")
+open class GmsCoreUtils {
+
+ class GmsCoreUtilsResult(var waitingForActivityResult: Boolean, var hasFinished: Boolean)
+
+ internal companion object {
+ private const val TAG = "GmsCoreUtils"
+
+ const val DEFAULT_REQUEST_CODE = 1
+
+ class FragmentCreationException() : Exception("Failed to create exception")
+
+ fun handleCreatePublicKeyCredential(
+ apiClient: Fido2ApiClient,
+ resultReceiver: ResultReceiver,
+ fidoRegistrationRequest: PublicKeyCredentialCreationOptions?,
+ requestCode: Int,
+ activity: Activity
+ ): GmsCoreUtilsResult {
+ var waitingForActivityResult = false
+ var hasActivityFinished = false
+ var fragment = setupFragmentActivity(activity, resultReceiver)
+
+ fidoRegistrationRequest?.let {
+ apiClient
+ .getRegisterPendingIntent(fidoRegistrationRequest)
+ .addOnSuccessListener { result: PendingIntent ->
+ try {
+ startIntentSender(
+ activity,
+ result.intentSender,
+ requestCode,
+ fragment,
+ )
+ } catch (e: IntentSender.SendIntentException) {
+ setupFailure(
+ resultReceiver,
+ CREATE_UNKNOWN,
+ "During public key credential, found IntentSender " +
+ "failure on public key creation: ${e.message}"
+ )
+ }
+ }
+ .addOnFailureListener { e: Exception ->
+ var errName: String = CREATE_UNKNOWN
+ if (e is ApiException && e.statusCode in CredentialProviderBaseController.retryables) {
+ errName = CREATE_INTERRUPTED
+ }
+ setupFailure(
+ resultReceiver,
+ errName,
+ "During create public key credential, fido registration " + "failure: ${e.message}"
+ )
+ }
+ }
+ ?: run {
+ Log.w(
+ TAG,
+ "During create public key credential, request is null, so nothing to " +
+ "launch for public key credentials"
+ )
+ hasActivityFinished = true
+ }
+ return GmsCoreUtilsResult(waitingForActivityResult, hasActivityFinished)
+ }
+
+ fun handleBeginSignIn(
+ apiClient: SignInClient,
+ resultReceiver: ResultReceiver,
+ params: BeginSignInRequest?,
+ requestCode: Int,
+ activity: Activity
+ ): GmsCoreUtilsResult {
+ var waitingForActivityResult = false
+ var hasFinished = false
+ var fragment = setupFragmentActivity(activity, resultReceiver)
+
+ params?.let {
+ apiClient
+ .beginSignIn(params)
+ .addOnSuccessListener {
+ try {
+ waitingForActivityResult = true
+ startIntentSender(
+ activity,
+ it.pendingIntent.intentSender,
+ requestCode,
+ fragment,
+ )
+ } catch (e: IntentSender.SendIntentException) {
+ setupFailure(
+ resultReceiver,
+ GET_UNKNOWN,
+ "During begin sign in, one tap ui intent sender " + "failure: ${e.message}"
+ )
+ }
+ }
+ .addOnFailureListener { e: Exception ->
+ var errName: String = GET_NO_CREDENTIALS
+ if (e is ApiException && e.statusCode in CredentialProviderBaseController.retryables) {
+ errName = GET_INTERRUPTED
+ }
+ setupFailure(
+ resultReceiver,
+ errName,
+ "During begin sign in, failure response from one tap: ${e.message}"
+ )
+ }
+ }
+ ?: run {
+ Log.i(
+ TAG,
+ "During begin sign in, params is null, nothing to launch for " + "begin sign in"
+ )
+ hasFinished = true
+ }
+ return GmsCoreUtilsResult(waitingForActivityResult, hasFinished)
+ }
+
+ fun handleCreatePassword(
+ apiClient: CredentialSavingClient,
+ resultReceiver: ResultReceiver,
+ params: SavePasswordRequest?,
+ requestCode: Int,
+ activity: Activity
+ ): GmsCoreUtilsResult {
+ var waitingForActivityResult = false
+ var hasFinished = false
+ var fragment = setupFragmentActivity(activity, resultReceiver)
+
+ params?.let {
+ apiClient
+ .savePassword(params)
+ .addOnSuccessListener {
+ try {
+ waitingForActivityResult = true
+ startIntentSender(
+ activity,
+ it.pendingIntent.intentSender,
+ requestCode,
+ fragment,
+ )
+ } catch (e: IntentSender.SendIntentException) {
+ setupFailure(
+ resultReceiver,
+ CREATE_UNKNOWN,
+ "During save password, found UI intent sender " + "failure: ${e.message}"
+ )
+ }
+ }
+ .addOnFailureListener { e: Exception ->
+ var errName: String = CREATE_UNKNOWN
+ if (e is ApiException && e.statusCode in CredentialProviderBaseController.retryables) {
+ errName = CREATE_INTERRUPTED
+ }
+ setupFailure(
+ resultReceiver,
+ errName,
+ "During save password, found " + "password failure response from one tap ${e.message}"
+ )
+ }
+ }
+ ?: run {
+ Log.i(
+ TAG,
+ "During save password, params is null, nothing to launch for create" + " password"
+ )
+ hasFinished = true
+ }
+ return GmsCoreUtilsResult(waitingForActivityResult, hasFinished)
+ }
+
+ private fun setupFragmentActivity(
+ activity: Activity,
+ resultReceiver: ResultReceiver
+ ): Fragment? {
+ if (activity is FragmentActivity) {
+ val fragment = CredentialProviderFragment.createFrom(resultReceiver)
+ val manager = activity.getSupportFragmentManager()
+ manager.beginTransaction().add(fragment, "credman").commit()
+
+ if (!fragment.isAdded()) {
+ throw FragmentCreationException()
+ }
+
+ return fragment
+ }
+
+ return null
+ }
+
+ private fun startIntentSender(
+ activity: Activity,
+ intentSender: IntentSender,
+ requestCode: Int,
+ fragment: Fragment?,
+ ) {
+ if (fragment != null && fragment.isAdded() && activity is FragmentActivity) {
+ activity.startIntentSenderFromFragment(
+ fragment,
+ intentSender,
+ requestCode,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ )
+ return
+ }
+
+ activity.startIntentSenderForResult(intentSender, requestCode, null, 0, 0, 0, null)
+ }
+
+ private fun setupFailure(resultReceiver: ResultReceiver, errName: String, errMsg: String) {
+ val bundle = Bundle()
+ bundle.putBoolean(CredentialProviderBaseController.FAILURE_RESPONSE_TAG, true)
+ bundle.putString(CredentialProviderBaseController.EXCEPTION_TYPE_TAG, errName)
+ bundle.putString(CredentialProviderBaseController.EXCEPTION_MESSAGE_TAG, errMsg)
+ resultReceiver.send(Integer.MAX_VALUE, bundle)
+ }
+ }
+}
diff --git a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/HiddenActivity.kt b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/HiddenActivity.kt
index faf3b6fd828..8586305fb2a 100644
--- a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/HiddenActivity.kt
+++ b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/HiddenActivity.kt
@@ -17,230 +17,150 @@
package androidx.credentials.playservices
import android.app.Activity
-import android.app.PendingIntent
import android.content.Intent
-import android.content.IntentSender
import android.os.Bundle
import android.os.ResultReceiver
import android.util.Log
import androidx.annotation.RestrictTo
import androidx.credentials.playservices.controllers.CredentialProviderBaseController
-import androidx.credentials.playservices.controllers.CredentialProviderBaseController.Companion.CREATE_INTERRUPTED
-import androidx.credentials.playservices.controllers.CredentialProviderBaseController.Companion.CREATE_UNKNOWN
-import androidx.credentials.playservices.controllers.CredentialProviderBaseController.Companion.GET_INTERRUPTED
-import androidx.credentials.playservices.controllers.CredentialProviderBaseController.Companion.GET_NO_CREDENTIALS
-import androidx.credentials.playservices.controllers.CredentialProviderBaseController.Companion.GET_UNKNOWN
import com.google.android.gms.auth.api.identity.BeginSignInRequest
import com.google.android.gms.auth.api.identity.Identity
import com.google.android.gms.auth.api.identity.SavePasswordRequest
-import com.google.android.gms.common.api.ApiException
import com.google.android.gms.fido.Fido
import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialCreationOptions
-/**
- * An activity used to ensure all required API versions work as intended.
- */
+/** An activity used to ensure all required API versions work as intended. */
@RestrictTo(RestrictTo.Scope.LIBRARY)
@Suppress("Deprecation", "ForbiddenSuperClass")
open class HiddenActivity : Activity() {
- private var resultReceiver: ResultReceiver? = null
- private var mWaitingForActivityResult = false
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- overridePendingTransition(0, 0)
- val type: String? = intent.getStringExtra(CredentialProviderBaseController.TYPE_TAG)
- resultReceiver = intent.getParcelableExtra(
- CredentialProviderBaseController.RESULT_RECEIVER_TAG)
-
- if (resultReceiver == null) {
- finish()
- }
-
- restoreState(savedInstanceState)
- if (mWaitingForActivityResult) {
- return; // Past call still active
- }
-
- when (type) {
- CredentialProviderBaseController.BEGIN_SIGN_IN_TAG -> {
- handleBeginSignIn()
- }
- CredentialProviderBaseController.CREATE_PASSWORD_TAG -> {
- handleCreatePassword()
- }
- CredentialProviderBaseController.CREATE_PUBLIC_KEY_CREDENTIAL_TAG -> {
- handleCreatePublicKeyCredential()
- } else -> {
- Log.w(TAG, "Activity handed an unsupported type")
- finish()
- }
- }
- }
+ private var resultReceiver: ResultReceiver? = null
+ private var mWaitingForActivityResult = false
- private fun restoreState(savedInstanceState: Bundle?) {
- if (savedInstanceState != null) {
- mWaitingForActivityResult = savedInstanceState.getBoolean(KEY_AWAITING_RESULT, false)
- }
- }
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ overridePendingTransition(0, 0)
+ val type: String? = intent.getStringExtra(CredentialProviderBaseController.TYPE_TAG)
+ resultReceiver = intent.getParcelableExtra(CredentialProviderBaseController.RESULT_RECEIVER_TAG)
- private fun handleCreatePublicKeyCredential() {
- val fidoRegistrationRequest: PublicKeyCredentialCreationOptions? = intent
- .getParcelableExtra(CredentialProviderBaseController.REQUEST_TAG)
- val requestCode: Int = intent.getIntExtra(
- CredentialProviderBaseController.ACTIVITY_REQUEST_CODE_TAG,
- DEFAULT_VALUE)
- fidoRegistrationRequest?.let {
- Fido.getFido2ApiClient(this)
- .getRegisterPendingIntent(fidoRegistrationRequest)
- .addOnSuccessListener { result: PendingIntent ->
- try {
- mWaitingForActivityResult = true
- startIntentSenderForResult(
- result.intentSender,
- requestCode,
- null, /* fillInIntent= */
- 0, /* flagsMask= */
- 0, /* flagsValue= */
- 0, /* extraFlags= */
- null /* options= */
- )
- } catch (e: IntentSender.SendIntentException) {
- setupFailure(resultReceiver!!,
- CREATE_UNKNOWN,
- "During public key credential, found IntentSender " +
- "failure on public key creation: ${e.message}")
- }
- }
- .addOnFailureListener { e: Exception ->
- var errName: String = CREATE_UNKNOWN
- if (e is ApiException && e.statusCode in
- CredentialProviderBaseController.retryables) {
- errName = CREATE_INTERRUPTED
- }
- setupFailure(resultReceiver!!, errName,
- "During create public key credential, fido registration " +
- "failure: ${e.message}")
- }
- } ?: run {
- Log.w(TAG, "During create public key credential, request is null, so nothing to " +
- "launch for public key credentials")
- finish()
- }
+ if (resultReceiver == null) {
+ finish()
}
- private fun setupFailure(resultReceiver: ResultReceiver, errName: String, errMsg: String) {
- val bundle = Bundle()
- bundle.putBoolean(CredentialProviderBaseController.FAILURE_RESPONSE_TAG, true)
- bundle.putString(CredentialProviderBaseController.EXCEPTION_TYPE_TAG, errName)
- bundle.putString(CredentialProviderBaseController.EXCEPTION_MESSAGE_TAG, errMsg)
- resultReceiver.send(Integer.MAX_VALUE, bundle)
- finish()
+ restoreState(savedInstanceState)
+ if (mWaitingForActivityResult) {
+ return
+ // Past call still active
}
- override fun onSaveInstanceState(outState: Bundle) {
- outState.putBoolean(KEY_AWAITING_RESULT, mWaitingForActivityResult)
- super.onSaveInstanceState(outState)
+ when (type) {
+ CredentialProviderBaseController.BEGIN_SIGN_IN_TAG -> {
+ handleBeginSignIn(intent, resultReceiver)
+ }
+ CredentialProviderBaseController.CREATE_PASSWORD_TAG -> {
+ handleCreatePassword(intent, resultReceiver)
+ }
+ CredentialProviderBaseController.CREATE_PUBLIC_KEY_CREDENTIAL_TAG -> {
+ handleCreatePublicKeyCredential(intent, resultReceiver)
+ }
+ else -> {
+ Log.w(TAG, "Activity handed an unsupported type")
+ finish()
+ }
}
+ }
- private fun handleBeginSignIn() {
- val params: BeginSignInRequest? = intent.getParcelableExtra(
- CredentialProviderBaseController.REQUEST_TAG)
- val requestCode: Int = intent.getIntExtra(
- CredentialProviderBaseController.ACTIVITY_REQUEST_CODE_TAG,
- DEFAULT_VALUE)
- params?.let {
- Identity.getSignInClient(this).beginSignIn(params).addOnSuccessListener {
- try {
- mWaitingForActivityResult = true
- startIntentSenderForResult(
- it.pendingIntent.intentSender,
- requestCode,
- null,
- 0,
- 0,
- 0,
- null
- )
- } catch (e: IntentSender.SendIntentException) {
- setupFailure(resultReceiver!!,
- GET_UNKNOWN,
- "During begin sign in, one tap ui intent sender " +
- "failure: ${e.message}")
- }
- }.addOnFailureListener { e: Exception ->
- var errName: String = GET_NO_CREDENTIALS
- if (e is ApiException && e.statusCode in
- CredentialProviderBaseController.retryables) {
- errName = GET_INTERRUPTED
- }
- setupFailure(resultReceiver!!, errName,
- "During begin sign in, failure response from one tap: ${e.message}")
- }
- } ?: run {
- Log.i(TAG, "During begin sign in, params is null, nothing to launch for " +
- "begin sign in")
- finish()
- }
+ private fun restoreState(savedInstanceState: Bundle?) {
+ if (savedInstanceState != null) {
+ mWaitingForActivityResult = savedInstanceState.getBoolean(KEY_AWAITING_RESULT, false)
}
-
- private fun handleCreatePassword() {
- val params: SavePasswordRequest? = intent.getParcelableExtra(
- CredentialProviderBaseController.REQUEST_TAG)
- val requestCode: Int = intent.getIntExtra(
- CredentialProviderBaseController.ACTIVITY_REQUEST_CODE_TAG,
- DEFAULT_VALUE)
- params?.let {
- Identity.getCredentialSavingClient(this).savePassword(params)
- .addOnSuccessListener {
- try {
- mWaitingForActivityResult = true
- startIntentSenderForResult(
- it.pendingIntent.intentSender,
- requestCode,
- null,
- 0,
- 0,
- 0,
- null
- )
- } catch (e: IntentSender.SendIntentException) {
- setupFailure(resultReceiver!!,
- CREATE_UNKNOWN,
- "During save password, found UI intent sender " +
- "failure: ${e.message}")
- }
- }.addOnFailureListener { e: Exception ->
- var errName: String = CREATE_UNKNOWN
- if (e is ApiException && e.statusCode in
- CredentialProviderBaseController.retryables) {
- errName = CREATE_INTERRUPTED
- }
- setupFailure(resultReceiver!!, errName, "During save password, found " +
- "password failure response from one tap ${e.message}")
- }
- } ?: run {
- Log.i(TAG, "During save password, params is null, nothing to launch for create" +
- " password")
- finish()
- }
+ }
+
+ private fun handleBeginSignIn(intent: Intent, resultReceiver: ResultReceiver?) {
+ val params: BeginSignInRequest? =
+ intent.getParcelableExtra(CredentialProviderBaseController.REQUEST_TAG)
+ val requestCode: Int =
+ intent.getIntExtra(CredentialProviderBaseController.ACTIVITY_REQUEST_CODE_TAG, DEFAULT_VALUE)
+
+ if (intent.hasExtra(CredentialProviderBaseController.REQUEST_TAG) && resultReceiver != null) {
+ val result =
+ GmsCoreUtils.handleBeginSignIn(
+ Identity.getSignInClient(this),
+ resultReceiver,
+ params!!,
+ requestCode,
+ this
+ )
+ mWaitingForActivityResult = result.waitingForActivityResult
+ if (result.hasFinished) {
+ finish()
+ }
}
-
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- super.onActivityResult(requestCode, resultCode, data)
- val bundle = Bundle()
- bundle.putBoolean(CredentialProviderBaseController.FAILURE_RESPONSE_TAG, false)
- bundle.putInt(CredentialProviderBaseController.ACTIVITY_REQUEST_CODE_TAG, requestCode)
- bundle.putParcelable(CredentialProviderBaseController.RESULT_DATA_TAG, data)
- resultReceiver?.send(resultCode, bundle)
- mWaitingForActivityResult = false
+ }
+
+ private fun handleCreatePassword(intent: Intent, resultReceiver: ResultReceiver?) {
+ val params: SavePasswordRequest? =
+ intent.getParcelableExtra(CredentialProviderBaseController.REQUEST_TAG)
+ val requestCode: Int =
+ intent.getIntExtra(CredentialProviderBaseController.ACTIVITY_REQUEST_CODE_TAG, DEFAULT_VALUE)
+
+ if (intent.hasExtra(CredentialProviderBaseController.REQUEST_TAG) && resultReceiver != null) {
+ val result =
+ GmsCoreUtils.handleCreatePassword(
+ Identity.getCredentialSavingClient(this),
+ resultReceiver,
+ params!!,
+ requestCode,
+ this
+ )
+ mWaitingForActivityResult = result.waitingForActivityResult
+ if (result.hasFinished) {
finish()
+ }
}
-
- companion object {
- private const val DEFAULT_VALUE: Int = 1
- private const val TAG = "HiddenActivity"
- private const val KEY_AWAITING_RESULT = "androidx.credentials.playservices.AWAITING_RESULT"
+ }
+
+ private fun handleCreatePublicKeyCredential(intent: Intent, resultReceiver: ResultReceiver?) {
+ val fidoRegistrationRequest: PublicKeyCredentialCreationOptions? =
+ intent.getParcelableExtra(CredentialProviderBaseController.REQUEST_TAG)
+ val requestCode: Int =
+ intent.getIntExtra(CredentialProviderBaseController.ACTIVITY_REQUEST_CODE_TAG, DEFAULT_VALUE)
+
+ if (intent.hasExtra(CredentialProviderBaseController.REQUEST_TAG) && resultReceiver != null) {
+ val result =
+ GmsCoreUtils.handleCreatePublicKeyCredential(
+ Fido.getFido2ApiClient(this),
+ resultReceiver,
+ fidoRegistrationRequest!!,
+ requestCode,
+ this
+ )
+ mWaitingForActivityResult = result.waitingForActivityResult
+ if (result.hasFinished) {
+ finish()
+ }
}
-} \ No newline at end of file
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ outState.putBoolean(KEY_AWAITING_RESULT, mWaitingForActivityResult)
+ super.onSaveInstanceState(outState)
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ val bundle = Bundle()
+ bundle.putBoolean(CredentialProviderBaseController.FAILURE_RESPONSE_TAG, false)
+ bundle.putInt(CredentialProviderBaseController.ACTIVITY_REQUEST_CODE_TAG, requestCode)
+ bundle.putParcelable(CredentialProviderBaseController.RESULT_DATA_TAG, data)
+ resultReceiver?.send(resultCode, bundle)
+ mWaitingForActivityResult = false
+ finish()
+ }
+
+ companion object {
+ private const val DEFAULT_VALUE: Int = 1
+ private const val TAG = "HiddenActivity"
+ private const val KEY_AWAITING_RESULT = "androidx.credentials.playservices.AWAITING_RESULT"
+ }
+}
diff --git a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/CredentialProviderBeginSignInController.kt b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/CredentialProviderBeginSignInController.kt
index b0d94538173..18f8a16b813 100644
--- a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/CredentialProviderBeginSignInController.kt
+++ b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/CredentialProviderBeginSignInController.kt
@@ -36,11 +36,13 @@ import androidx.credentials.exceptions.GetCredentialException
import androidx.credentials.exceptions.GetCredentialInterruptedException
import androidx.credentials.exceptions.GetCredentialUnknownException
import androidx.credentials.playservices.CredentialProviderPlayServicesImpl
+import androidx.credentials.playservices.GmsCoreUtils
import androidx.credentials.playservices.HiddenActivity
import androidx.credentials.playservices.controllers.BeginSignIn.BeginSignInControllerUtility.Companion.constructBeginSignInRequest
import androidx.credentials.playservices.controllers.CreatePublicKeyCredential.PublicKeyCredentialControllerUtility
import androidx.credentials.playservices.controllers.CredentialProviderBaseController
import androidx.credentials.playservices.controllers.CredentialProviderController
+import androidx.fragment.app.FragmentActivity
import com.google.android.gms.auth.api.identity.BeginSignInRequest
import com.google.android.gms.auth.api.identity.Identity
import com.google.android.gms.auth.api.identity.SignInCredential
@@ -117,6 +119,20 @@ internal class CredentialProviderBeginSignInController(private val context: Cont
}
val convertedRequest: BeginSignInRequest = this.convertRequestToPlayServices(request)
+
+ // If we were passed a fragment activity use that instead of a hidden one.
+ if (context is FragmentActivity) {
+ try {
+ GmsCoreUtils.handleBeginSignIn(
+ Identity.getSignInClient(context),
+ resultReceiver, convertedRequest, GmsCoreUtils.DEFAULT_REQUEST_CODE,
+ context)
+ return
+ } catch (e: Exception) {
+ Log.e(TAG, "Failed to use fragment flow", e)
+ }
+ }
+
val hiddenIntent = Intent(context, HiddenActivity::class.java)
hiddenIntent.putExtra(REQUEST_TAG, convertedRequest)
generateHiddenActivityIntent(resultReceiver, hiddenIntent, BEGIN_SIGN_IN_TAG)
diff --git a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePassword/CredentialProviderCreatePasswordController.kt b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePassword/CredentialProviderCreatePasswordController.kt
index 360b0c61251..ee4c3bb23ae 100644
--- a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePassword/CredentialProviderCreatePasswordController.kt
+++ b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePassword/CredentialProviderCreatePasswordController.kt
@@ -32,9 +32,12 @@ import androidx.credentials.CredentialManagerCallback
import androidx.credentials.exceptions.CreateCredentialException
import androidx.credentials.exceptions.CreateCredentialUnknownException
import androidx.credentials.playservices.CredentialProviderPlayServicesImpl
+import androidx.credentials.playservices.GmsCoreUtils
import androidx.credentials.playservices.HiddenActivity
import androidx.credentials.playservices.controllers.CredentialProviderBaseController
import androidx.credentials.playservices.controllers.CredentialProviderController
+import androidx.fragment.app.FragmentActivity
+import com.google.android.gms.auth.api.identity.Identity
import com.google.android.gms.auth.api.identity.SavePasswordRequest
import com.google.android.gms.auth.api.identity.SignInPassword
import java.util.concurrent.Executor
@@ -100,6 +103,20 @@ internal class CredentialProviderCreatePasswordController(private val context: C
}
val convertedRequest: SavePasswordRequest = this.convertRequestToPlayServices(request)
+
+ // If we were passed a fragment activity use that instead of a hidden one.
+ if (context is FragmentActivity) {
+ try {
+ GmsCoreUtils.handleCreatePassword(
+ Identity.getCredentialSavingClient(context),
+ resultReceiver, convertedRequest, GmsCoreUtils.DEFAULT_REQUEST_CODE,
+ context)
+ return
+ } catch (e: Exception) {
+ Log.e(TAG, "Failed to use fragment flow", e)
+ }
+ }
+
val hiddenIntent = Intent(context, HiddenActivity::class.java)
hiddenIntent.putExtra(REQUEST_TAG, convertedRequest)
generateHiddenActivityIntent(resultReceiver, hiddenIntent, CREATE_PASSWORD_TAG)
diff --git a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePublicKeyCredential/CredentialProviderCreatePublicKeyCredentialController.kt b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePublicKeyCredential/CredentialProviderCreatePublicKeyCredentialController.kt
index 7f3a2693ef9..15420581f40 100644
--- a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePublicKeyCredential/CredentialProviderCreatePublicKeyCredentialController.kt
+++ b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePublicKeyCredential/CredentialProviderCreatePublicKeyCredentialController.kt
@@ -35,9 +35,11 @@ import androidx.credentials.exceptions.domerrors.EncodingError
import androidx.credentials.exceptions.domerrors.UnknownError
import androidx.credentials.exceptions.publickeycredential.CreatePublicKeyCredentialDomException
import androidx.credentials.playservices.CredentialProviderPlayServicesImpl
+import androidx.credentials.playservices.GmsCoreUtils
import androidx.credentials.playservices.HiddenActivity
import androidx.credentials.playservices.controllers.CredentialProviderBaseController
import androidx.credentials.playservices.controllers.CredentialProviderController
+import androidx.fragment.app.FragmentActivity
import com.google.android.gms.fido.Fido
import com.google.android.gms.fido.fido2.api.common.PublicKeyCredential
import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialCreationOptions
@@ -120,6 +122,19 @@ internal class CredentialProviderCreatePublicKeyCredentialController(private val
if (CredentialProviderPlayServicesImpl.cancellationReviewer(cancellationSignal)) {
return
}
+
+ // If we were passed a fragment activity use that instead of a hidden one.
+ if (context is FragmentActivity) {
+ try {
+ GmsCoreUtils.handleCreatePublicKeyCredential(Fido.getFido2ApiClient(context),
+ resultReceiver, fidoRegistrationRequest, GmsCoreUtils.DEFAULT_REQUEST_CODE,
+ context)
+ return
+ } catch (e: Exception) {
+ Log.e(TAG, "Failed to use fragment flow", e)
+ }
+ }
+
val hiddenIntent = Intent(context, HiddenActivity::class.java)
hiddenIntent.putExtra(REQUEST_TAG, fidoRegistrationRequest)
generateHiddenActivityIntent(resultReceiver, hiddenIntent,