Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion appcheck/firebase-appcheck-recaptchaenterprise/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.google.firebase.appcheck.recaptchaenterprise {

public class RecaptchaEnterpriseAppCheckProviderFactory implements com.google.firebase.appcheck.AppCheckProviderFactory {
method public com.google.firebase.appcheck.AppCheckProvider create(com.google.firebase.FirebaseApp);
method public static com.google.firebase.appcheck.recaptchaenterprise.RecaptchaEnterpriseAppCheckProviderFactory getInstance(String);
method public static com.google.firebase.appcheck.recaptchaenterprise.RecaptchaEnterpriseAppCheckProviderFactory getInstance();
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ dependencies {
implementation(libs.dagger.dagger)

api project(':appcheck:firebase-appcheck')
api libs.firebase.common
api project(':firebase-common')
api libs.firebase.components
api 'com.google.android.recaptcha:recaptcha:18.7.1'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,48 +15,40 @@
package com.google.firebase.appcheck.recaptchaenterprise;

import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.Preconditions;
import com.google.firebase.FirebaseApp;
import com.google.firebase.appcheck.AppCheckProvider;
import com.google.firebase.appcheck.AppCheckProviderFactory;
import com.google.firebase.appcheck.FirebaseAppCheck;
import com.google.firebase.appcheck.recaptchaenterprise.internal.ProviderMultiResourceComponent;
import com.google.firebase.appcheck.recaptchaenterprise.internal.RecaptchaEnterpriseAppCheckProvider;
import java.util.Objects;

/**
* Implementation of an {@link AppCheckProviderFactory} that builds <br>
* {@link RecaptchaEnterpriseAppCheckProvider}s. This is the default implementation.
*/
public class RecaptchaEnterpriseAppCheckProviderFactory implements AppCheckProviderFactory {

private final String siteKey;
private volatile RecaptchaEnterpriseAppCheckProvider provider;

private RecaptchaEnterpriseAppCheckProviderFactory(@NonNull String siteKey) {
this.siteKey = siteKey;
}
private RecaptchaEnterpriseAppCheckProviderFactory() {}

/** Gets an instance of this class for installation into a {@link FirebaseAppCheck} instance. */
@NonNull
public static RecaptchaEnterpriseAppCheckProviderFactory getInstance(@NonNull String siteKey) {
Objects.requireNonNull(siteKey, "siteKey cannot be null");
return new RecaptchaEnterpriseAppCheckProviderFactory(siteKey);
public static RecaptchaEnterpriseAppCheckProviderFactory getInstance() {
return new RecaptchaEnterpriseAppCheckProviderFactory();
}

@NonNull
@Override
@SuppressWarnings("FirebaseUseExplicitDependencies")
public AppCheckProvider create(@NonNull FirebaseApp firebaseApp) {
if (provider == null) {
synchronized (this) {
if (provider == null) {
ProviderMultiResourceComponent component =
firebaseApp.get(ProviderMultiResourceComponent.class);
provider = component.get(siteKey);
provider.initializeRecaptchaClient();
}
}
}
String siteKey = firebaseApp.getOptions().getRecaptchaSiteKey();
Preconditions.checkNotEmpty(
siteKey,
"Missing site key from configuration. Verify your google-services.json file is updated.");
ProviderMultiResourceComponent component =
firebaseApp.get(ProviderMultiResourceComponent.class);
RecaptchaEnterpriseAppCheckProvider provider = component.get(siteKey);
provider.initializeRecaptchaClient();
return provider;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,61 +24,74 @@
import static org.mockito.Mockito.when;

import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.appcheck.AppCheckProvider;
import com.google.firebase.appcheck.recaptchaenterprise.internal.ProviderMultiResourceComponent;
import com.google.firebase.appcheck.recaptchaenterprise.internal.RecaptchaEnterpriseAppCheckProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

/** Tests for {@link RecaptchaEnterpriseAppCheckProviderFactory}. */
@RunWith(MockitoJUnitRunner.class)
@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class RecaptchaEnterpriseAppCheckProviderFactoryTest {
static final String SITE_KEY_1 = "siteKey1";

@Mock private FirebaseApp mockFirebaseApp;
@Mock private FirebaseOptions mockFirebaseOptions;
@Mock private ProviderMultiResourceComponent mockComponent;
@Mock private RecaptchaEnterpriseAppCheckProvider mockProvider;

@Before
public void setUp() {
MockitoAnnotations.openMocks(this);
when(mockFirebaseApp.get(eq(ProviderMultiResourceComponent.class))).thenReturn(mockComponent);
when(mockComponent.get(anyString())).thenReturn(mockProvider);
when(mockFirebaseApp.getOptions()).thenReturn(mockFirebaseOptions);
}

@Test
public void getInstance_nonNullSiteKey_returnsNonNullInstance() {
public void getInstance_returnsNonNullInstance() {
RecaptchaEnterpriseAppCheckProviderFactory factory =
RecaptchaEnterpriseAppCheckProviderFactory.getInstance(SITE_KEY_1);
RecaptchaEnterpriseAppCheckProviderFactory.getInstance();
assertNotNull(factory);
}

@Test
public void getInstance_nullSiteKey_expectThrows() {
assertThrows(
NullPointerException.class,
() -> RecaptchaEnterpriseAppCheckProviderFactory.getInstance(null));
}

@Test
public void create_nonNullFirebaseApp_returnsRecaptchaEnterpriseAppCheckProvider() {
public void create_siteKeyInOptions_returnsRecaptchaEnterpriseAppCheckProvider() {
when(mockFirebaseOptions.getRecaptchaSiteKey()).thenReturn(SITE_KEY_1);
RecaptchaEnterpriseAppCheckProviderFactory factory =
RecaptchaEnterpriseAppCheckProviderFactory.getInstance(SITE_KEY_1);
RecaptchaEnterpriseAppCheckProviderFactory.getInstance();
AppCheckProvider provider = factory.create(mockFirebaseApp);
assertNotNull(provider);
assertEquals(RecaptchaEnterpriseAppCheckProvider.class, provider.getClass());
verify(mockComponent).get(SITE_KEY_1);
}

@Test
public void create_noSiteKeyInOptionsOrFactory_expectThrows() {
when(mockFirebaseOptions.getRecaptchaSiteKey()).thenReturn(null);
RecaptchaEnterpriseAppCheckProviderFactory factory =
RecaptchaEnterpriseAppCheckProviderFactory.getInstance();
assertThrows(IllegalArgumentException.class, () -> factory.create(mockFirebaseApp));
}

@Test
public void create_callMultipleTimes_providerIsInitializedOnlyOnce() {
public void create_callMultipleTimes_initializesProviderEveryTime() {
when(mockFirebaseOptions.getRecaptchaSiteKey()).thenReturn(SITE_KEY_1);
RecaptchaEnterpriseAppCheckProviderFactory factory =
RecaptchaEnterpriseAppCheckProviderFactory.getInstance(SITE_KEY_1);
RecaptchaEnterpriseAppCheckProviderFactory.getInstance();

factory.create(mockFirebaseApp);
factory.create(mockFirebaseApp);
factory.create(mockFirebaseApp);
verify(mockProvider, times(1)).initializeRecaptchaClient();

verify(mockComponent, times(3)).get(SITE_KEY_1);
verify(mockProvider, times(3)).initializeRecaptchaClient();
}
}
Loading