diff --git a/appcheck/firebase-appcheck-debug-testing/CHANGELOG.md b/appcheck/firebase-appcheck-debug-testing/CHANGELOG.md index e9a4b2de744..4de30c64161 100644 --- a/appcheck/firebase-appcheck-debug-testing/CHANGELOG.md +++ b/appcheck/firebase-appcheck-debug-testing/CHANGELOG.md @@ -1,4 +1,5 @@ # Unreleased +* [changed] Integrated the [app_check] Debug Testing SDK with Firebase Components. (#4436) # 16.1.0 * [unchanged] Updated to accommodate the release of the updated diff --git a/appcheck/firebase-appcheck-debug/CHANGELOG.md b/appcheck/firebase-appcheck-debug/CHANGELOG.md index b23c1898f40..c056a58c51e 100644 --- a/appcheck/firebase-appcheck-debug/CHANGELOG.md +++ b/appcheck/firebase-appcheck-debug/CHANGELOG.md @@ -1,4 +1,6 @@ # Unreleased +* [changed] Migrated [app_check] SDKs to use standard Firebase executors. (#4431, #4449) +* [changed] Integrated the [app_check] Debug SDK with Firebase Components. (#4436) # 16.1.0 * [unchanged] Updated to accommodate the release of the updated diff --git a/appcheck/firebase-appcheck-debug/firebase-appcheck-debug.gradle b/appcheck/firebase-appcheck-debug/firebase-appcheck-debug.gradle index 80cad7da537..bbfce8aa822 100644 --- a/appcheck/firebase-appcheck-debug/firebase-appcheck-debug.gradle +++ b/appcheck/firebase-appcheck-debug/firebase-appcheck-debug.gradle @@ -41,6 +41,7 @@ android { } dependencies { + implementation project(':firebase-annotations') implementation project(':firebase-common') implementation project(':firebase-components') implementation project(':appcheck:firebase-appcheck') @@ -49,6 +50,7 @@ dependencies { javadocClasspath 'com.google.auto.value:auto-value-annotations:1.6.6' + testImplementation project(':integ-testing') testImplementation 'junit:junit:4.13-beta-2' testImplementation 'org.mockito:mockito-core:2.25.0' testImplementation "org.robolectric:robolectric:$robolectricVersion" diff --git a/appcheck/firebase-appcheck-debug/src/main/java/com/google/firebase/appcheck/debug/FirebaseAppCheckDebugRegistrar.java b/appcheck/firebase-appcheck-debug/src/main/java/com/google/firebase/appcheck/debug/FirebaseAppCheckDebugRegistrar.java index e321d20c743..dd0730b83c7 100644 --- a/appcheck/firebase-appcheck-debug/src/main/java/com/google/firebase/appcheck/debug/FirebaseAppCheckDebugRegistrar.java +++ b/appcheck/firebase-appcheck-debug/src/main/java/com/google/firebase/appcheck/debug/FirebaseAppCheckDebugRegistrar.java @@ -16,13 +16,17 @@ import com.google.android.gms.common.annotation.KeepForSdk; import com.google.firebase.FirebaseApp; +import com.google.firebase.annotations.concurrent.Background; +import com.google.firebase.annotations.concurrent.Blocking; import com.google.firebase.appcheck.debug.internal.DebugAppCheckProvider; import com.google.firebase.components.Component; import com.google.firebase.components.ComponentRegistrar; import com.google.firebase.components.Dependency; +import com.google.firebase.components.Qualified; import com.google.firebase.platforminfo.LibraryVersionComponent; import java.util.Arrays; import java.util.List; +import java.util.concurrent.Executor; /** * {@link ComponentRegistrar} for setting up FirebaseAppCheck debug's dependency injections in @@ -36,16 +40,23 @@ public class FirebaseAppCheckDebugRegistrar implements ComponentRegistrar { @Override public List> getComponents() { + Qualified backgroundExecutor = Qualified.qualified(Background.class, Executor.class); + Qualified blockingExecutor = Qualified.qualified(Blocking.class, Executor.class); + return Arrays.asList( Component.builder(DebugAppCheckProvider.class) .name(LIBRARY_NAME) .add(Dependency.required(FirebaseApp.class)) .add(Dependency.optionalProvider(InternalDebugSecretProvider.class)) + .add(Dependency.required(backgroundExecutor)) + .add(Dependency.required(blockingExecutor)) .factory( (container) -> new DebugAppCheckProvider( container.get(FirebaseApp.class), - container.getProvider(InternalDebugSecretProvider.class))) + container.getProvider(InternalDebugSecretProvider.class), + container.get(backgroundExecutor), + container.get(blockingExecutor))) .build(), LibraryVersionComponent.create(LIBRARY_NAME, BuildConfig.VERSION_NAME)); } diff --git a/appcheck/firebase-appcheck-debug/src/main/java/com/google/firebase/appcheck/debug/internal/DebugAppCheckProvider.java b/appcheck/firebase-appcheck-debug/src/main/java/com/google/firebase/appcheck/debug/internal/DebugAppCheckProvider.java index 84bdd7f408a..632e7eec0e0 100644 --- a/appcheck/firebase-appcheck-debug/src/main/java/com/google/firebase/appcheck/debug/internal/DebugAppCheckProvider.java +++ b/appcheck/firebase-appcheck-debug/src/main/java/com/google/firebase/appcheck/debug/internal/DebugAppCheckProvider.java @@ -24,6 +24,8 @@ import com.google.android.gms.tasks.TaskCompletionSource; import com.google.android.gms.tasks.Tasks; import com.google.firebase.FirebaseApp; +import com.google.firebase.annotations.concurrent.Background; +import com.google.firebase.annotations.concurrent.Blocking; import com.google.firebase.appcheck.AppCheckProvider; import com.google.firebase.appcheck.AppCheckToken; import com.google.firebase.appcheck.debug.InternalDebugSecretProvider; @@ -32,8 +34,7 @@ import com.google.firebase.appcheck.internal.RetryManager; import com.google.firebase.inject.Provider; import java.util.UUID; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +import java.util.concurrent.Executor; public class DebugAppCheckProvider implements AppCheckProvider { @@ -41,18 +42,18 @@ public class DebugAppCheckProvider implements AppCheckProvider { private static final String UTF_8 = "UTF-8"; private final NetworkClient networkClient; - private final ExecutorService backgroundExecutor; + private final Executor blockingExecutor; private final RetryManager retryManager; private final Task debugSecretTask; - // TODO(b/258273630): Migrate to go/firebase-android-executors - @SuppressLint("ThreadPoolCreation") public DebugAppCheckProvider( @NonNull FirebaseApp firebaseApp, - @NonNull Provider debugSecretProvider) { + @NonNull Provider debugSecretProvider, + @Background Executor backgroundExecutor, + @Blocking Executor blockingExecutor) { checkNotNull(firebaseApp); this.networkClient = new NetworkClient(firebaseApp); - this.backgroundExecutor = Executors.newCachedThreadPool(); + this.blockingExecutor = blockingExecutor; this.retryManager = new RetryManager(); String debugSecret = null; @@ -61,7 +62,7 @@ public DebugAppCheckProvider( } this.debugSecretTask = debugSecret == null - ? determineDebugSecret(firebaseApp, this.backgroundExecutor) + ? determineDebugSecret(firebaseApp, backgroundExecutor) : Tasks.forResult(debugSecret); } @@ -69,10 +70,10 @@ public DebugAppCheckProvider( DebugAppCheckProvider( @NonNull String debugSecret, @NonNull NetworkClient networkClient, - @NonNull ExecutorService backgroundExecutor, + @NonNull Executor blockingExecutor, @NonNull RetryManager retryManager) { this.networkClient = networkClient; - this.backgroundExecutor = backgroundExecutor; + this.blockingExecutor = blockingExecutor; this.retryManager = retryManager; this.debugSecretTask = Tasks.forResult(debugSecret); } @@ -80,7 +81,7 @@ public DebugAppCheckProvider( @VisibleForTesting @NonNull static Task determineDebugSecret( - @NonNull FirebaseApp firebaseApp, @NonNull ExecutorService executor) { + @NonNull FirebaseApp firebaseApp, @NonNull Executor executor) { TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); executor.execute( () -> { @@ -111,7 +112,7 @@ public Task getToken() { task -> { ExchangeDebugTokenRequest request = new ExchangeDebugTokenRequest(task.getResult()); return Tasks.call( - backgroundExecutor, + blockingExecutor, () -> networkClient.exchangeAttestationForAppCheckToken( request.toJsonString().getBytes(UTF_8), diff --git a/appcheck/firebase-appcheck-debug/src/test/java/com/google/firebase/appcheck/debug/FirebaseAppCheckDebugRegistrarTest.java b/appcheck/firebase-appcheck-debug/src/test/java/com/google/firebase/appcheck/debug/FirebaseAppCheckDebugRegistrarTest.java index 7a9dbc5c482..5de65d9251a 100644 --- a/appcheck/firebase-appcheck-debug/src/test/java/com/google/firebase/appcheck/debug/FirebaseAppCheckDebugRegistrarTest.java +++ b/appcheck/firebase-appcheck-debug/src/test/java/com/google/firebase/appcheck/debug/FirebaseAppCheckDebugRegistrarTest.java @@ -17,9 +17,13 @@ import static com.google.common.truth.Truth.assertThat; import com.google.firebase.FirebaseApp; +import com.google.firebase.annotations.concurrent.Background; +import com.google.firebase.annotations.concurrent.Blocking; import com.google.firebase.components.Component; import com.google.firebase.components.Dependency; +import com.google.firebase.components.Qualified; import java.util.List; +import java.util.concurrent.Executor; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @@ -37,7 +41,9 @@ public void testGetComponents() { assertThat(appCheckDebugComponent.getDependencies()) .containsExactly( Dependency.required(FirebaseApp.class), - Dependency.optionalProvider(InternalDebugSecretProvider.class)); + Dependency.optionalProvider(InternalDebugSecretProvider.class), + Dependency.required(Qualified.qualified(Background.class, Executor.class)), + Dependency.required(Qualified.qualified(Blocking.class, Executor.class))); assertThat(appCheckDebugComponent.isLazy()).isTrue(); } } diff --git a/appcheck/firebase-appcheck-debug/src/test/java/com/google/firebase/appcheck/debug/internal/DebugAppCheckProviderTest.java b/appcheck/firebase-appcheck-debug/src/test/java/com/google/firebase/appcheck/debug/internal/DebugAppCheckProviderTest.java index 3d53b398fd2..46fe2be778f 100644 --- a/appcheck/firebase-appcheck-debug/src/test/java/com/google/firebase/appcheck/debug/internal/DebugAppCheckProviderTest.java +++ b/appcheck/firebase-appcheck-debug/src/test/java/com/google/firebase/appcheck/debug/internal/DebugAppCheckProviderTest.java @@ -33,8 +33,9 @@ import com.google.firebase.appcheck.internal.DefaultAppCheckToken; import com.google.firebase.appcheck.internal.NetworkClient; import com.google.firebase.appcheck.internal.RetryManager; +import com.google.firebase.concurrent.TestOnlyExecutors; import java.io.IOException; -import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executor; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -72,7 +73,8 @@ public class DebugAppCheckProviderTest { private StorageHelper storageHelper; private SharedPreferences sharedPreferences; - private ExecutorService backgroundExecutor = MoreExecutors.newDirectExecutorService(); + // TODO(b/258273630): Use TestOnlyExecutors instead of MoreExecutors.directExecutor(). + private Executor executor = MoreExecutors.directExecutor(); @Before public void setup() { @@ -100,7 +102,8 @@ public void testPublicConstructor_nullFirebaseApp_expectThrows() { assertThrows( NullPointerException.class, () -> { - new DebugAppCheckProvider(null, null); + new DebugAppCheckProvider( + null, null, TestOnlyExecutors.background(), TestOnlyExecutors.blocking()); }); } @@ -110,7 +113,7 @@ public void testDetermineDebugSecret_noStoredSecret_createsNewSecret() { assertThat(storageHelper.retrieveDebugSecret()).isNull(); Task debugSecretTask = - DebugAppCheckProvider.determineDebugSecret(mockFirebaseApp, backgroundExecutor); + DebugAppCheckProvider.determineDebugSecret(mockFirebaseApp, executor); assertThat(storageHelper.retrieveDebugSecret()).isNotNull(); assertThat(storageHelper.retrieveDebugSecret()).isEqualTo(debugSecretTask.getResult()); } @@ -120,7 +123,7 @@ public void testDetermineDebugSecret_storedSecret_usesExistingSecret() { storageHelper.saveDebugSecret(DEBUG_SECRET); Task debugSecretTask = - DebugAppCheckProvider.determineDebugSecret(mockFirebaseApp, backgroundExecutor); + DebugAppCheckProvider.determineDebugSecret(mockFirebaseApp, executor); assertThat(debugSecretTask.getResult()).isEqualTo(DEBUG_SECRET); assertThat(storageHelper.retrieveDebugSecret()).isEqualTo(DEBUG_SECRET); } @@ -134,8 +137,7 @@ public void exchangeDebugToken_onSuccess_setsTaskResult() throws Exception { when(mockAppCheckTokenResponse.getTimeToLive()).thenReturn(TIME_TO_LIVE); DebugAppCheckProvider provider = - new DebugAppCheckProvider( - DEBUG_SECRET, mockNetworkClient, backgroundExecutor, mockRetryManager); + new DebugAppCheckProvider(DEBUG_SECRET, mockNetworkClient, executor, mockRetryManager); Task task = provider.getToken(); verify(mockNetworkClient) @@ -153,8 +155,7 @@ public void exchangeDebugToken_onFailure_setsTaskException() throws Exception { .thenThrow(new IOException()); DebugAppCheckProvider provider = - new DebugAppCheckProvider( - DEBUG_SECRET, mockNetworkClient, backgroundExecutor, mockRetryManager); + new DebugAppCheckProvider(DEBUG_SECRET, mockNetworkClient, executor, mockRetryManager); Task task = provider.getToken(); verify(mockNetworkClient) diff --git a/appcheck/firebase-appcheck-playintegrity/CHANGELOG.md b/appcheck/firebase-appcheck-playintegrity/CHANGELOG.md index bdea5a89161..f709e9e9ab3 100644 --- a/appcheck/firebase-appcheck-playintegrity/CHANGELOG.md +++ b/appcheck/firebase-appcheck-playintegrity/CHANGELOG.md @@ -1,4 +1,6 @@ # Unreleased +* [changed] Migrated [app_check] SDKs to use standard Firebase executors. (#4431, #4449) +* [changed] Integrated the [app_check] Play Integrity SDK with Firebase Components. (#4436) # 16.1.0 * [unchanged] Updated to accommodate the release of the updated diff --git a/appcheck/firebase-appcheck-playintegrity/firebase-appcheck-playintegrity.gradle b/appcheck/firebase-appcheck-playintegrity/firebase-appcheck-playintegrity.gradle index 92dcf4806c9..185558a75c5 100644 --- a/appcheck/firebase-appcheck-playintegrity/firebase-appcheck-playintegrity.gradle +++ b/appcheck/firebase-appcheck-playintegrity/firebase-appcheck-playintegrity.gradle @@ -41,6 +41,7 @@ android { } dependencies { + implementation project(':firebase-annotations') implementation project(':firebase-common') implementation project(':firebase-components') implementation project(':appcheck:firebase-appcheck') @@ -50,6 +51,7 @@ dependencies { javadocClasspath 'com.google.auto.value:auto-value-annotations:1.6.6' + testImplementation project(':integ-testing') testImplementation 'junit:junit:4.13.2' testImplementation 'org.mockito:mockito-core:3.4.6' testImplementation "com.google.truth:truth:$googleTruthVersion" diff --git a/appcheck/firebase-appcheck-playintegrity/src/main/java/com/google/firebase/appcheck/playintegrity/FirebaseAppCheckPlayIntegrityRegistrar.java b/appcheck/firebase-appcheck-playintegrity/src/main/java/com/google/firebase/appcheck/playintegrity/FirebaseAppCheckPlayIntegrityRegistrar.java index d5c0f2d8908..96eb55128f0 100644 --- a/appcheck/firebase-appcheck-playintegrity/src/main/java/com/google/firebase/appcheck/playintegrity/FirebaseAppCheckPlayIntegrityRegistrar.java +++ b/appcheck/firebase-appcheck-playintegrity/src/main/java/com/google/firebase/appcheck/playintegrity/FirebaseAppCheckPlayIntegrityRegistrar.java @@ -16,13 +16,16 @@ import com.google.android.gms.common.annotation.KeepForSdk; import com.google.firebase.FirebaseApp; +import com.google.firebase.annotations.concurrent.Blocking; import com.google.firebase.appcheck.playintegrity.internal.PlayIntegrityAppCheckProvider; import com.google.firebase.components.Component; import com.google.firebase.components.ComponentRegistrar; import com.google.firebase.components.Dependency; +import com.google.firebase.components.Qualified; import com.google.firebase.platforminfo.LibraryVersionComponent; import java.util.Arrays; import java.util.List; +import java.util.concurrent.Executor; /** * {@link ComponentRegistrar} for setting up FirebaseAppCheck play integrity's dependency injections @@ -36,12 +39,17 @@ public class FirebaseAppCheckPlayIntegrityRegistrar implements ComponentRegistra @Override public List> getComponents() { + Qualified blockingExecutor = Qualified.qualified(Blocking.class, Executor.class); + return Arrays.asList( Component.builder(PlayIntegrityAppCheckProvider.class) .name(LIBRARY_NAME) .add(Dependency.required(FirebaseApp.class)) + .add(Dependency.required(blockingExecutor)) .factory( - (container) -> new PlayIntegrityAppCheckProvider(container.get(FirebaseApp.class))) + (container) -> + new PlayIntegrityAppCheckProvider( + container.get(FirebaseApp.class), container.get(blockingExecutor))) .build(), LibraryVersionComponent.create(LIBRARY_NAME, BuildConfig.VERSION_NAME)); } diff --git a/appcheck/firebase-appcheck-playintegrity/src/main/java/com/google/firebase/appcheck/playintegrity/internal/PlayIntegrityAppCheckProvider.java b/appcheck/firebase-appcheck-playintegrity/src/main/java/com/google/firebase/appcheck/playintegrity/internal/PlayIntegrityAppCheckProvider.java index a7484436965..1a90d4b8d2e 100644 --- a/appcheck/firebase-appcheck-playintegrity/src/main/java/com/google/firebase/appcheck/playintegrity/internal/PlayIntegrityAppCheckProvider.java +++ b/appcheck/firebase-appcheck-playintegrity/src/main/java/com/google/firebase/appcheck/playintegrity/internal/PlayIntegrityAppCheckProvider.java @@ -24,13 +24,13 @@ import com.google.android.play.core.integrity.IntegrityTokenRequest; import com.google.android.play.core.integrity.IntegrityTokenResponse; import com.google.firebase.FirebaseApp; +import com.google.firebase.annotations.concurrent.Blocking; import com.google.firebase.appcheck.AppCheckProvider; import com.google.firebase.appcheck.AppCheckToken; import com.google.firebase.appcheck.internal.DefaultAppCheckToken; import com.google.firebase.appcheck.internal.NetworkClient; import com.google.firebase.appcheck.internal.RetryManager; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +import java.util.concurrent.Executor; public class PlayIntegrityAppCheckProvider implements AppCheckProvider { @@ -39,17 +39,16 @@ public class PlayIntegrityAppCheckProvider implements AppCheckProvider { private final String projectNumber; private final IntegrityManager integrityManager; private final NetworkClient networkClient; - private final ExecutorService backgroundExecutor; + private final Executor blockingExecutor; private final RetryManager retryManager; - // TODO(b/258273630): Migrate to go/firebase-android-executors - @SuppressLint("ThreadPoolCreation") - public PlayIntegrityAppCheckProvider(@NonNull FirebaseApp firebaseApp) { + public PlayIntegrityAppCheckProvider( + @NonNull FirebaseApp firebaseApp, @Blocking Executor blockingExecutor) { this( firebaseApp.getOptions().getGcmSenderId(), IntegrityManagerFactory.create(firebaseApp.getApplicationContext()), new NetworkClient(firebaseApp), - Executors.newCachedThreadPool(), + blockingExecutor, new RetryManager()); } @@ -58,12 +57,12 @@ public PlayIntegrityAppCheckProvider(@NonNull FirebaseApp firebaseApp) { @NonNull String projectNumber, @NonNull IntegrityManager integrityManager, @NonNull NetworkClient networkClient, - @NonNull ExecutorService backgroundExecutor, + @NonNull Executor blockingExecutor, @NonNull RetryManager retryManager) { this.projectNumber = projectNumber; this.integrityManager = integrityManager; this.networkClient = networkClient; - this.backgroundExecutor = backgroundExecutor; + this.blockingExecutor = blockingExecutor; this.retryManager = retryManager; } @@ -78,7 +77,7 @@ public Task getToken() { ExchangePlayIntegrityTokenRequest request = new ExchangePlayIntegrityTokenRequest(integrityTokenResponse.token()); return Tasks.call( - backgroundExecutor, + blockingExecutor, () -> networkClient.exchangeAttestationForAppCheckToken( request.toJsonString().getBytes(UTF_8), @@ -100,7 +99,7 @@ private Task getPlayIntegrityAttestation() { new GeneratePlayIntegrityChallengeRequest(); Task generateChallengeTask = Tasks.call( - backgroundExecutor, + blockingExecutor, () -> GeneratePlayIntegrityChallengeResponse.fromJsonString( networkClient.generatePlayIntegrityChallenge( diff --git a/appcheck/firebase-appcheck-playintegrity/src/test/java/com/google/firebase/appcheck/playintegrity/FirebaseAppCheckPlayIntegrityRegistrarTest.java b/appcheck/firebase-appcheck-playintegrity/src/test/java/com/google/firebase/appcheck/playintegrity/FirebaseAppCheckPlayIntegrityRegistrarTest.java index 78dcc325162..b6e4d2f1855 100644 --- a/appcheck/firebase-appcheck-playintegrity/src/test/java/com/google/firebase/appcheck/playintegrity/FirebaseAppCheckPlayIntegrityRegistrarTest.java +++ b/appcheck/firebase-appcheck-playintegrity/src/test/java/com/google/firebase/appcheck/playintegrity/FirebaseAppCheckPlayIntegrityRegistrarTest.java @@ -17,9 +17,12 @@ import static com.google.common.truth.Truth.assertThat; import com.google.firebase.FirebaseApp; +import com.google.firebase.annotations.concurrent.Blocking; import com.google.firebase.components.Component; import com.google.firebase.components.Dependency; +import com.google.firebase.components.Qualified; import java.util.List; +import java.util.concurrent.Executor; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @@ -35,7 +38,9 @@ public void testGetComponents() { assertThat(components).hasSize(2); Component appCheckPlayIntegrityComponent = components.get(0); assertThat(appCheckPlayIntegrityComponent.getDependencies()) - .containsExactly(Dependency.required(FirebaseApp.class)); + .containsExactly( + Dependency.required(FirebaseApp.class), + Dependency.required(Qualified.qualified(Blocking.class, Executor.class))); assertThat(appCheckPlayIntegrityComponent.isLazy()).isTrue(); } } diff --git a/appcheck/firebase-appcheck-playintegrity/src/test/java/com/google/firebase/appcheck/playintegrity/internal/PlayIntegrityAppCheckProviderTest.java b/appcheck/firebase-appcheck-playintegrity/src/test/java/com/google/firebase/appcheck/playintegrity/internal/PlayIntegrityAppCheckProviderTest.java index 4d748b7d78f..6d2fc50825e 100644 --- a/appcheck/firebase-appcheck-playintegrity/src/test/java/com/google/firebase/appcheck/playintegrity/internal/PlayIntegrityAppCheckProviderTest.java +++ b/appcheck/firebase-appcheck-playintegrity/src/test/java/com/google/firebase/appcheck/playintegrity/internal/PlayIntegrityAppCheckProviderTest.java @@ -34,8 +34,9 @@ import com.google.firebase.appcheck.internal.DefaultAppCheckToken; import com.google.firebase.appcheck.internal.NetworkClient; import com.google.firebase.appcheck.internal.RetryManager; +import com.google.firebase.concurrent.TestOnlyExecutors; import java.io.IOException; -import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executor; import java.util.concurrent.TimeoutException; import org.json.JSONObject; import org.junit.Before; @@ -70,7 +71,8 @@ public class PlayIntegrityAppCheckProviderTest { @Captor private ArgumentCaptor integrityTokenRequestCaptor; @Captor private ArgumentCaptor exchangePlayIntegrityTokenRequestCaptor; - private ExecutorService backgroundExecutor = MoreExecutors.newDirectExecutorService(); + // TODO(b/258273630): Use TestOnlyExecutors instead of MoreExecutors.directExecutor(). + private Executor backgroundExecutor = MoreExecutors.directExecutor(); @Before public void setup() { @@ -85,7 +87,7 @@ public void testPublicConstructor_nullFirebaseApp_expectThrows() { assertThrows( NullPointerException.class, () -> { - new PlayIntegrityAppCheckProvider(null); + new PlayIntegrityAppCheckProvider(null, TestOnlyExecutors.blocking()); }); } diff --git a/appcheck/firebase-appcheck-safetynet/CHANGELOG.md b/appcheck/firebase-appcheck-safetynet/CHANGELOG.md index 39e56b1e276..30951fed0e2 100644 --- a/appcheck/firebase-appcheck-safetynet/CHANGELOG.md +++ b/appcheck/firebase-appcheck-safetynet/CHANGELOG.md @@ -1,4 +1,6 @@ # Unreleased +* [changed] Migrated [app_check] SDKs to use standard Firebase executors. (#4431, #4449) +* [changed] Integrated the [app_check] SafetyNet SDK with Firebase Components. (#4436) # 16.1.0 * [unchanged] Updated to accommodate the release of the updated diff --git a/appcheck/firebase-appcheck-safetynet/firebase-appcheck-safetynet.gradle b/appcheck/firebase-appcheck-safetynet/firebase-appcheck-safetynet.gradle index f9b52b74e06..d4ef33efdad 100644 --- a/appcheck/firebase-appcheck-safetynet/firebase-appcheck-safetynet.gradle +++ b/appcheck/firebase-appcheck-safetynet/firebase-appcheck-safetynet.gradle @@ -41,6 +41,7 @@ android { } dependencies { + implementation project(':firebase-annotations') implementation project(':firebase-common') implementation project(':firebase-components') implementation project(':appcheck:firebase-appcheck') @@ -51,6 +52,7 @@ dependencies { javadocClasspath 'com.google.auto.value:auto-value-annotations:1.6.6' javadocClasspath 'org.checkerframework:checker-qual:2.5.2' + testImplementation project(':integ-testing') testImplementation 'junit:junit:4.13-beta-2' testImplementation 'org.mockito:mockito-core:2.25.0' testImplementation "org.robolectric:robolectric:$robolectricVersion" diff --git a/appcheck/firebase-appcheck-safetynet/src/main/java/com/google/firebase/appcheck/safetynet/FirebaseAppCheckSafetyNetRegistrar.java b/appcheck/firebase-appcheck-safetynet/src/main/java/com/google/firebase/appcheck/safetynet/FirebaseAppCheckSafetyNetRegistrar.java index a532b25e546..ddf42818d60 100644 --- a/appcheck/firebase-appcheck-safetynet/src/main/java/com/google/firebase/appcheck/safetynet/FirebaseAppCheckSafetyNetRegistrar.java +++ b/appcheck/firebase-appcheck-safetynet/src/main/java/com/google/firebase/appcheck/safetynet/FirebaseAppCheckSafetyNetRegistrar.java @@ -16,13 +16,17 @@ import com.google.android.gms.common.annotation.KeepForSdk; import com.google.firebase.FirebaseApp; +import com.google.firebase.annotations.concurrent.Background; +import com.google.firebase.annotations.concurrent.Blocking; import com.google.firebase.appcheck.safetynet.internal.SafetyNetAppCheckProvider; import com.google.firebase.components.Component; import com.google.firebase.components.ComponentRegistrar; import com.google.firebase.components.Dependency; +import com.google.firebase.components.Qualified; import com.google.firebase.platforminfo.LibraryVersionComponent; import java.util.Arrays; import java.util.List; +import java.util.concurrent.Executor; /** * {@link ComponentRegistrar} for setting up FirebaseAppCheck safety net's dependency injections in @@ -36,11 +40,21 @@ public class FirebaseAppCheckSafetyNetRegistrar implements ComponentRegistrar { @Override public List> getComponents() { + Qualified backgroundExecutor = Qualified.qualified(Background.class, Executor.class); + Qualified blockingExecutor = Qualified.qualified(Blocking.class, Executor.class); + return Arrays.asList( Component.builder(SafetyNetAppCheckProvider.class) .name(LIBRARY_NAME) .add(Dependency.required(FirebaseApp.class)) - .factory((container) -> new SafetyNetAppCheckProvider(container.get(FirebaseApp.class))) + .add(Dependency.required(backgroundExecutor)) + .add(Dependency.required(blockingExecutor)) + .factory( + (container) -> + new SafetyNetAppCheckProvider( + container.get(FirebaseApp.class), + container.get(backgroundExecutor), + container.get(blockingExecutor))) .build(), LibraryVersionComponent.create(LIBRARY_NAME, BuildConfig.VERSION_NAME)); } diff --git a/appcheck/firebase-appcheck-safetynet/src/main/java/com/google/firebase/appcheck/safetynet/internal/SafetyNetAppCheckProvider.java b/appcheck/firebase-appcheck-safetynet/src/main/java/com/google/firebase/appcheck/safetynet/internal/SafetyNetAppCheckProvider.java index 22f043fd57d..c646305df26 100644 --- a/appcheck/firebase-appcheck-safetynet/src/main/java/com/google/firebase/appcheck/safetynet/internal/SafetyNetAppCheckProvider.java +++ b/appcheck/firebase-appcheck-safetynet/src/main/java/com/google/firebase/appcheck/safetynet/internal/SafetyNetAppCheckProvider.java @@ -30,14 +30,15 @@ import com.google.android.gms.tasks.TaskCompletionSource; import com.google.android.gms.tasks.Tasks; import com.google.firebase.FirebaseApp; +import com.google.firebase.annotations.concurrent.Background; +import com.google.firebase.annotations.concurrent.Blocking; import com.google.firebase.appcheck.AppCheckProvider; import com.google.firebase.appcheck.AppCheckToken; import com.google.firebase.appcheck.internal.AppCheckTokenResponse; import com.google.firebase.appcheck.internal.DefaultAppCheckToken; import com.google.firebase.appcheck.internal.NetworkClient; import com.google.firebase.appcheck.internal.RetryManager; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +import java.util.concurrent.Executor; public class SafetyNetAppCheckProvider implements AppCheckProvider { @@ -48,22 +49,23 @@ public class SafetyNetAppCheckProvider implements AppCheckProvider { private static final String NONCE = ""; private static final String UTF_8 = "UTF-8"; - private final Context context; private final Task safetyNetClientTask; private final NetworkClient networkClient; - private final ExecutorService backgroundExecutor; + private final Executor blockingExecutor; private final RetryManager retryManager; private final String apiKey; /** @param firebaseApp the FirebaseApp to which this Factory is tied. */ - // TODO(b/258273630): Migrate to go/firebase-android-executors - @SuppressLint("ThreadPoolCreation") - public SafetyNetAppCheckProvider(@NonNull FirebaseApp firebaseApp) { + public SafetyNetAppCheckProvider( + @NonNull FirebaseApp firebaseApp, + @Background Executor backgroundExecutor, + @Blocking Executor blockingExecutor) { this( firebaseApp, new NetworkClient(firebaseApp), GoogleApiAvailability.getInstance(), - Executors.newCachedThreadPool()); + backgroundExecutor, + blockingExecutor); } @VisibleForTesting @@ -71,15 +73,17 @@ public SafetyNetAppCheckProvider(@NonNull FirebaseApp firebaseApp) { @NonNull FirebaseApp firebaseApp, @NonNull NetworkClient networkClient, @NonNull GoogleApiAvailability googleApiAvailability, - @NonNull ExecutorService backgroundExecutor) { + @NonNull Executor backgroundExecutor, + @NonNull Executor blockingExecutor) { checkNotNull(firebaseApp); checkNotNull(networkClient); checkNotNull(googleApiAvailability); checkNotNull(backgroundExecutor); - this.context = firebaseApp.getApplicationContext(); this.apiKey = firebaseApp.getOptions().getApiKey(); - this.backgroundExecutor = backgroundExecutor; - this.safetyNetClientTask = initSafetyNetClient(googleApiAvailability, this.backgroundExecutor); + this.blockingExecutor = blockingExecutor; + this.safetyNetClientTask = + initSafetyNetClient( + firebaseApp.getApplicationContext(), googleApiAvailability, backgroundExecutor); this.networkClient = networkClient; this.retryManager = new RetryManager(); } @@ -89,18 +93,17 @@ public SafetyNetAppCheckProvider(@NonNull FirebaseApp firebaseApp) { @NonNull FirebaseApp firebaseApp, @NonNull SafetyNetClient safetyNetClient, @NonNull NetworkClient networkClient, - @NonNull ExecutorService backgroundExecutor, + @NonNull Executor blockingExecutor, @NonNull RetryManager retryManager) { - this.context = firebaseApp.getApplicationContext(); this.apiKey = firebaseApp.getOptions().getApiKey(); this.safetyNetClientTask = Tasks.forResult(safetyNetClient); this.networkClient = networkClient; - this.backgroundExecutor = backgroundExecutor; + this.blockingExecutor = blockingExecutor; this.retryManager = retryManager; } - private Task initSafetyNetClient( - GoogleApiAvailability googleApiAvailability, ExecutorService executor) { + private static Task initSafetyNetClient( + Context context, GoogleApiAvailability googleApiAvailability, Executor executor) { TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); executor.execute( () -> { @@ -117,7 +120,7 @@ private Task initSafetyNetClient( return taskCompletionSource.getTask(); } - private String getGooglePlayServicesConnectionErrorString(int connectionResult) { + private static String getGooglePlayServicesConnectionErrorString(int connectionResult) { switch (connectionResult) { case ConnectionResult.SERVICE_MISSING: return "Google Play services is missing on this device."; @@ -179,7 +182,7 @@ Task exchangeSafetyNetAttestationResponseForToken( Task networkTask = Tasks.call( - backgroundExecutor, + blockingExecutor, () -> networkClient.exchangeAttestationForAppCheckToken( request.toJsonString().getBytes(UTF_8), diff --git a/appcheck/firebase-appcheck-safetynet/src/test/java/com/google/firebase/appcheck/safetynet/FirebaseAppCheckSafetyNetRegistrarTest.java b/appcheck/firebase-appcheck-safetynet/src/test/java/com/google/firebase/appcheck/safetynet/FirebaseAppCheckSafetyNetRegistrarTest.java index b944561a32c..c62ba1b0d20 100644 --- a/appcheck/firebase-appcheck-safetynet/src/test/java/com/google/firebase/appcheck/safetynet/FirebaseAppCheckSafetyNetRegistrarTest.java +++ b/appcheck/firebase-appcheck-safetynet/src/test/java/com/google/firebase/appcheck/safetynet/FirebaseAppCheckSafetyNetRegistrarTest.java @@ -17,9 +17,13 @@ import static com.google.common.truth.Truth.assertThat; import com.google.firebase.FirebaseApp; +import com.google.firebase.annotations.concurrent.Background; +import com.google.firebase.annotations.concurrent.Blocking; import com.google.firebase.components.Component; import com.google.firebase.components.Dependency; +import com.google.firebase.components.Qualified; import java.util.List; +import java.util.concurrent.Executor; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @@ -35,7 +39,10 @@ public void testGetComponents() { assertThat(components).hasSize(2); Component appCheckSafetyNetComponent = components.get(0); assertThat(appCheckSafetyNetComponent.getDependencies()) - .containsExactly(Dependency.required(FirebaseApp.class)); + .containsExactly( + Dependency.required(FirebaseApp.class), + Dependency.required(Qualified.qualified(Background.class, Executor.class)), + Dependency.required(Qualified.qualified(Blocking.class, Executor.class))); assertThat(appCheckSafetyNetComponent.isLazy()).isTrue(); } } diff --git a/appcheck/firebase-appcheck-safetynet/src/test/java/com/google/firebase/appcheck/safetynet/internal/SafetyNetAppCheckProviderTest.java b/appcheck/firebase-appcheck-safetynet/src/test/java/com/google/firebase/appcheck/safetynet/internal/SafetyNetAppCheckProviderTest.java index 6072e3693f1..befca9ce751 100644 --- a/appcheck/firebase-appcheck-safetynet/src/test/java/com/google/firebase/appcheck/safetynet/internal/SafetyNetAppCheckProviderTest.java +++ b/appcheck/firebase-appcheck-safetynet/src/test/java/com/google/firebase/appcheck/safetynet/internal/SafetyNetAppCheckProviderTest.java @@ -37,8 +37,8 @@ import com.google.firebase.appcheck.internal.DefaultAppCheckToken; import com.google.firebase.appcheck.internal.NetworkClient; import com.google.firebase.appcheck.internal.RetryManager; +import com.google.firebase.concurrent.TestOnlyExecutors; import java.io.IOException; -import java.util.concurrent.ExecutorService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -62,7 +62,6 @@ public class SafetyNetAppCheckProviderTest { private static final String TIME_TO_LIVE = "3600s"; private FirebaseApp firebaseApp; - private ExecutorService backgroundExecutor = MoreExecutors.newDirectExecutorService(); @Mock private GoogleApiAvailability mockGoogleApiAvailability; @Mock private SafetyNetClient mockSafetyNetClient; @Mock private NetworkClient mockNetworkClient; @@ -84,7 +83,8 @@ public void testPublicConstructor_nullFirebaseApp_expectThrows() { assertThrows( NullPointerException.class, () -> { - new SafetyNetAppCheckProvider(null); + new SafetyNetAppCheckProvider( + null, TestOnlyExecutors.background(), TestOnlyExecutors.blocking()); }); } @@ -95,7 +95,11 @@ public void testPublicConstructor_nullFirebaseApp_expectThrows() { .thenReturn(ConnectionResult.SERVICE_MISSING); SafetyNetAppCheckProvider provider = new SafetyNetAppCheckProvider( - firebaseApp, mockNetworkClient, mockGoogleApiAvailability, backgroundExecutor); + firebaseApp, + mockNetworkClient, + mockGoogleApiAvailability, + TestOnlyExecutors.background(), + TestOnlyExecutors.blocking()); assertThat(provider.getSafetyNetClientTask().isSuccessful()).isFalse(); } @@ -105,7 +109,11 @@ public void testGetToken_googlePlayServicesIsNotAvailable_expectGetTokenTaskExce .thenReturn(ConnectionResult.SERVICE_MISSING); SafetyNetAppCheckProvider provider = new SafetyNetAppCheckProvider( - firebaseApp, mockNetworkClient, mockGoogleApiAvailability, backgroundExecutor); + firebaseApp, + mockNetworkClient, + mockGoogleApiAvailability, + TestOnlyExecutors.background(), + TestOnlyExecutors.blocking()); assertThat(provider.getSafetyNetClientTask().isSuccessful()).isFalse(); Task tokenTask = provider.getToken(); @@ -120,7 +128,7 @@ public void testGetToken_nonNullSafetyNetClient_expectCallsSafetyNetForAttestati firebaseApp, mockSafetyNetClient, mockNetworkClient, - backgroundExecutor, + TestOnlyExecutors.blocking(), mockRetryManager); assertThat(provider.getSafetyNetClientTask().getResult()).isEqualTo(mockSafetyNetClient); @@ -142,7 +150,7 @@ public void testExchangeSafetyNetJwsForToken_nullAttestationResponse_expectThrow firebaseApp, mockSafetyNetClient, mockNetworkClient, - backgroundExecutor, + TestOnlyExecutors.blocking(), mockRetryManager); assertThrows( NullPointerException.class, @@ -160,7 +168,7 @@ public void testExchangeSafetyNetJwsForToken_emptySafetyNetJwsResult_expectThrow firebaseApp, mockSafetyNetClient, mockNetworkClient, - backgroundExecutor, + TestOnlyExecutors.blocking(), mockRetryManager); assertThrows( IllegalArgumentException.class, @@ -177,7 +185,7 @@ public void testExchangeSafetyNetJwsForToken_validFields_expectReturnsTask() { firebaseApp, mockSafetyNetClient, mockNetworkClient, - backgroundExecutor, + TestOnlyExecutors.blocking(), mockRetryManager); Task task = provider.exchangeSafetyNetAttestationResponseForToken(mockSafetyNetAttestationResponse); @@ -193,12 +201,13 @@ public void exchangeSafetyNetJwsForToken_onSuccess_setsTaskResult() throws Excep when(mockAppCheckTokenResponse.getToken()).thenReturn(APP_CHECK_TOKEN); when(mockAppCheckTokenResponse.getTimeToLive()).thenReturn(TIME_TO_LIVE); + // TODO(b/258273630): Use TestOnlyExecutors instead of MoreExecutors.directExecutor(). SafetyNetAppCheckProvider provider = new SafetyNetAppCheckProvider( firebaseApp, mockSafetyNetClient, mockNetworkClient, - backgroundExecutor, + MoreExecutors.directExecutor(), mockRetryManager); Task task = provider.exchangeSafetyNetAttestationResponseForToken(mockSafetyNetAttestationResponse); @@ -219,12 +228,13 @@ public void exchangeSafetyNetJwsForToken_onFailure_setsTaskException() throws Ex any(), eq(NetworkClient.SAFETY_NET), eq(mockRetryManager))) .thenThrow(new IOException()); + // TODO(b/258273630): Use TestOnlyExecutors instead of MoreExecutors.directExecutor(). SafetyNetAppCheckProvider provider = new SafetyNetAppCheckProvider( firebaseApp, mockSafetyNetClient, mockNetworkClient, - backgroundExecutor, + MoreExecutors.directExecutor(), mockRetryManager); Task task = provider.exchangeSafetyNetAttestationResponseForToken(mockSafetyNetAttestationResponse); diff --git a/appcheck/firebase-appcheck/CHANGELOG.md b/appcheck/firebase-appcheck/CHANGELOG.md index 34188c9770c..dae41a8ace7 100644 --- a/appcheck/firebase-appcheck/CHANGELOG.md +++ b/appcheck/firebase-appcheck/CHANGELOG.md @@ -1,5 +1,5 @@ # Unreleased -* [changed] Migrated the `firebase-appcheck` library to use standard Firebase executors. (#4431) +* [changed] Migrated [app_check] SDKs to use standard Firebase executors. (#4431, #4449) # 16.1.0 * [unchanged] Updated to accommodate the release of the updated