diff --git a/firebase-dynamic-links/firebase-dynamic-links.gradle b/firebase-dynamic-links/firebase-dynamic-links.gradle index 17789583af8..127a3f4c643 100644 --- a/firebase-dynamic-links/firebase-dynamic-links.gradle +++ b/firebase-dynamic-links/firebase-dynamic-links.gradle @@ -29,7 +29,7 @@ android { compileSdkVersion project.targetSdkVersion defaultConfig { targetSdkVersion project.targetSdkVersion - minSdkVersion project.minSdkVersion + minSdkVersion 16 versionName version multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -51,31 +51,34 @@ dependencies { implementation project(':firebase-common') implementation project(':firebase-components') - implementation 'androidx.annotation:annotation:1.1.0' + implementation 'androidx.annotation:annotation:1.2.0' - implementation 'com.google.android.gms:play-services-basement:17.0.0' - implementation 'com.google.android.gms:play-services-tasks:17.0.0' - implementation 'com.google.android.gms:play-services-base:17.0.0' + implementation 'com.google.android.gms:play-services-basement:17.6.0' + implementation 'com.google.android.gms:play-services-tasks:17.2.1' + implementation 'com.google.android.gms:play-services-base:17.6.0' - implementation('com.google.firebase:firebase-auth-interop:18.0.0') { + implementation('com.google.firebase:firebase-auth-interop:20.0.0') { exclude group: "com.google.firebase", module: "firebase-common" } - implementation('com.google.firebase:firebase-measurement-connector:18.0.0') { + implementation('com.google.firebase:firebase-measurement-connector:19.0.0') { exclude group: 'com.google.firebase', module: 'firebase-common' } + testCompileOnly 'com.google.auto.value:auto-value-annotations:1.6.3' + testAnnotationProcessor "com.google.auto.value:auto-value:1.6.3" javadocClasspath 'com.google.auto.value:auto-value-annotations:1.6.6' + javadocClasspath 'com.google.code.findbugs:jsr305:3.0.2' - testImplementation 'junit:junit:4.12' - testImplementation 'androidx.test:core:1.2.0' - testImplementation 'com.android.support.test:runner:1.0.1' - testImplementation 'org.mockito:mockito-core:2.25.0' + testImplementation 'junit:junit:4.13.2' + testImplementation 'androidx.test:core:1.3.0' + testImplementation 'com.android.support.test:runner:1.0.2' + testImplementation 'org.mockito:mockito-core:3.3.3' testImplementation "org.robolectric:robolectric:$robolectricVersion" testImplementation "com.google.truth:truth:$googleTruthVersion" - testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8' + testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.10.2' testImplementation 'com.google.guava:guava-testlib:12.0-rc2' - testImplementation('com.google.android.gms:play-services-appinvite:16.0.0') { + testImplementation('com.google.android.gms:play-services-appinvite:18.0.0') { exclude group: 'com.google.firebase', module: 'firebase-common' exclude group: 'com.google.firebase', module: 'firebase-dynamic-links' } diff --git a/firebase-dynamic-links/src/main/AndroidManifest.xml b/firebase-dynamic-links/src/main/AndroidManifest.xml index 4f35452be3c..a04d2b01c73 100644 --- a/firebase-dynamic-links/src/main/AndroidManifest.xml +++ b/firebase-dynamic-links/src/main/AndroidManifest.xml @@ -19,11 +19,10 @@ + android:exported="false"> - diff --git a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/DynamicLink.java b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/DynamicLink.java index 89fd366c447..145da1b96bb 100644 --- a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/DynamicLink.java +++ b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/DynamicLink.java @@ -1,4 +1,4 @@ -// Copyright 2018 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -94,10 +94,8 @@ public static final class Builder { public Builder(FirebaseDynamicLinksImpl firebaseDynamicLinks) { firebaseDynamicLinksImpl = firebaseDynamicLinks; builderParameters = new Bundle(); - if (FirebaseApp.getInstance() != null) { - builderParameters.putString( - KEY_API_KEY, FirebaseApp.getInstance().getOptions().getApiKey()); - } + builderParameters.putString( + KEY_API_KEY, firebaseDynamicLinks.getFirebaseApp().getOptions().getApiKey()); fdlParameters = new Bundle(); builderParameters.putBundle(KEY_DYNAMIC_LINK_PARAMETERS, fdlParameters); } diff --git a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/FirebaseDynamicLinks.java b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/FirebaseDynamicLinks.java index 6b2a3c98734..80e363cc0f2 100644 --- a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/FirebaseDynamicLinks.java +++ b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/FirebaseDynamicLinks.java @@ -1,4 +1,4 @@ -// Copyright 2018 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/PendingDynamicLinkData.java b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/PendingDynamicLinkData.java index a6f11f9ba3d..71425fd4568 100644 --- a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/PendingDynamicLinkData.java +++ b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/PendingDynamicLinkData.java @@ -1,4 +1,4 @@ -// Copyright 2018 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,23 +21,25 @@ import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; import com.google.android.gms.common.GooglePlayServicesUtil; +import com.google.android.gms.common.annotation.KeepForSdk; import com.google.android.gms.common.util.DefaultClock; +import com.google.android.gms.common.util.VisibleForTesting; import com.google.firebase.dynamiclinks.internal.DynamicLinkData; import com.google.firebase.dynamiclinks.internal.DynamicLinkUTMParams; /** Provides accessor methods to dynamic links data. */ public class PendingDynamicLinkData { - private final DynamicLinkData dynamicLinkData; @Nullable private final DynamicLinkUTMParams dynamicLinkUTMParams; + @Nullable private final DynamicLinkData dynamicLinkData; /** * Create a dynamic link from parameters. * * @hide */ + @KeepForSdk @VisibleForTesting public PendingDynamicLinkData(DynamicLinkData dynamicLinkData) { if (dynamicLinkData == null) { @@ -77,6 +79,7 @@ protected PendingDynamicLinkData( * @return A bundle will all extension data. * @hide */ + @KeepForSdk @Nullable public Bundle getExtensions() { if (dynamicLinkData == null) { @@ -114,7 +117,7 @@ public Uri getLink() { @NonNull public Bundle getUtmParameters() { if (dynamicLinkUTMParams == null) { - return Bundle.EMPTY; + return new Bundle(); } return dynamicLinkUTMParams.asBundle(); @@ -156,6 +159,7 @@ public long getClickTimestamp() { * @hide */ @VisibleForTesting + @Nullable public Uri getRedirectUrl() { if (dynamicLinkData == null) { return null; diff --git a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/ShortDynamicLink.java b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/ShortDynamicLink.java index 4af37dc143e..c679c5de7b2 100644 --- a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/ShortDynamicLink.java +++ b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/ShortDynamicLink.java @@ -1,4 +1,4 @@ -// Copyright 2018 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinkData.java b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinkData.java index f49fa8640c0..55ed19f9fec 100644 --- a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinkData.java +++ b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinkData.java @@ -1,4 +1,4 @@ -// Copyright 2018 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Parcel; +import androidx.annotation.Nullable; import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable; import com.google.android.gms.common.internal.safeparcel.SafeParcelable; @@ -25,9 +26,11 @@ public class DynamicLinkData extends AbstractSafeParcelable { @SafeParcelable.Field(id = 1, getter = "getDynamicLink") + @Nullable private String dynamicLink; @SafeParcelable.Field(id = 2, getter = "getDeepLink") + @Nullable private String deepLink; @SafeParcelable.Field(id = 3, getter = "getMinVersion") @@ -37,11 +40,14 @@ public class DynamicLinkData extends AbstractSafeParcelable { private long clickTimestamp = 0L; @SafeParcelable.Field(id = 5, getter = "getExtensionBundle") + @Nullable private Bundle extensionBundle = null; @SafeParcelable.Field(id = 6, getter = "getRedirectUrl") + @Nullable private Uri redirectUrl; + @Nullable public String getDynamicLink() { return dynamicLink; } @@ -50,6 +56,7 @@ public void setDynamicLink(String dynamicLink) { this.dynamicLink = dynamicLink; } + @Nullable public String getDeepLink() { return deepLink; } @@ -82,6 +89,7 @@ public void setRedirectUrl(Uri redirectUrl) { this.redirectUrl = redirectUrl; } + @Nullable public Uri getRedirectUrl() { return redirectUrl; } @@ -101,12 +109,12 @@ public void setExtensionData(Bundle bundle) { @SafeParcelable.Constructor public DynamicLinkData( - @Param(id = 1) String dynamicLink, - @Param(id = 2) String deepLink, + @Nullable @Param(id = 1) String dynamicLink, + @Nullable @Param(id = 2) String deepLink, @Param(id = 3) int minVersion, @Param(id = 4) long clickTimestamp, - @Param(id = 5) Bundle extensions, - @Param(id = 6) Uri redirectUrl) { + @Nullable @Param(id = 5) Bundle extensions, + @Nullable @Param(id = 6) Uri redirectUrl) { this.dynamicLink = dynamicLink; this.deepLink = deepLink; this.minVersion = minVersion; diff --git a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinkDataCreator.java b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinkDataCreator.java index ebcc2c38197..f539780b63f 100644 --- a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinkDataCreator.java +++ b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinkDataCreator.java @@ -1,4 +1,4 @@ -// Copyright 2018 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinkUTMParams.java b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinkUTMParams.java index ffddf796e76..b8e5ee4ab89 100644 --- a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinkUTMParams.java +++ b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinkUTMParams.java @@ -44,7 +44,7 @@ public class DynamicLinkUTMParams { public DynamicLinkUTMParams(DynamicLinkData dynamicLinkData) { this.dynamicLinkData = dynamicLinkData; - this.utmParamsBundle = initUTMParamsBundle(); + this.utmParamsBundle = initUTMParamsBundle(dynamicLinkData); } @NonNull @@ -52,26 +52,28 @@ public Bundle asBundle() { return new Bundle(utmParamsBundle); } - private Bundle initUTMParamsBundle() { + @NonNull + private static Bundle initUTMParamsBundle(DynamicLinkData dynamicLinkData) { + Bundle bundle = new Bundle(); if (dynamicLinkData == null || dynamicLinkData.getExtensionBundle() == null) { - return Bundle.EMPTY; + return bundle; } Bundle scionBundle = dynamicLinkData.getExtensionBundle().getBundle(KEY_SCION_DATA_BUNDLE); if (scionBundle == null) { - return Bundle.EMPTY; + return bundle; } Bundle campaignBundle = scionBundle.getBundle(KEY_CAMPAIGN_BUNDLE); if (campaignBundle == null) { - return Bundle.EMPTY; + return bundle; } - Bundle bundle = new Bundle(); checkAndAdd(KEY_MEDIUM, KEY_UTM_MEDIUM, campaignBundle, bundle); checkAndAdd(KEY_SOURCE, KEY_UTM_SOURCE, campaignBundle, bundle); checkAndAdd(KEY_CAMPAIGN, KEY_UTM_CAMPAIGN, campaignBundle, bundle); + return bundle; } @@ -79,7 +81,7 @@ private Bundle initUTMParamsBundle() { * Checks and adds the value from source bundle to the destination bundle based on the source * key and destination key. */ - private void checkAndAdd( + private static void checkAndAdd( @NonNull String sourceKey, @NonNull String destKey, @NonNull Bundle source, diff --git a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinksApi.java b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinksApi.java index 599cafd1d0e..32c08a906ec 100644 --- a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinksApi.java +++ b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinksApi.java @@ -1,4 +1,4 @@ -// Copyright 2018 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,13 +17,14 @@ import android.content.Context; import android.os.Looper; import androidx.annotation.NonNull; -import androidx.annotation.VisibleForTesting; import com.google.android.gms.common.api.Api; +import com.google.android.gms.common.api.Api.ApiOptions; import com.google.android.gms.common.api.Api.ApiOptions.NoOptions; import com.google.android.gms.common.api.GoogleApi; import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks; import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener; import com.google.android.gms.common.internal.ClientSettings; +import com.google.android.gms.common.util.VisibleForTesting; public class DynamicLinksApi extends GoogleApi { @@ -63,6 +64,6 @@ public DynamicLinksClient buildClient( */ @VisibleForTesting public DynamicLinksApi(@NonNull Context context) { - super(context, API, null /* options */, Settings.DEFAULT_SETTINGS); + super(context, API, ApiOptions.NO_OPTIONS /* options */, Settings.DEFAULT_SETTINGS); } } diff --git a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinksClient.java b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinksClient.java index 694db565812..18936f7d286 100644 --- a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinksClient.java +++ b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinksClient.java @@ -1,4 +1,4 @@ -// Copyright 2018 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -32,6 +32,8 @@ public class DynamicLinksClient extends GmsClient { "com.google.firebase.dynamiclinks.service.START"; public static final String SERVICE_DESCRIPTOR = "com.google.firebase.dynamiclinks.internal.IDynamicLinksService"; + private static final int DYNAMIC_LINKS_API_VALUE = 131; + private static final int V17 = 12451000; public DynamicLinksClient( Context context, @@ -42,8 +44,7 @@ public DynamicLinksClient( super( context, looper, - // ServiceId.DYNAMIC_LINKS_API_VALUE, - 131, + DYNAMIC_LINKS_API_VALUE, clientSettings, connectedListener, connectionFailedListener); @@ -67,7 +68,7 @@ protected IDynamicLinksService createServiceInterface(IBinder binder) { return IDynamicLinksService.Stub.asInterface(binder); } - void getDynamicLink(IDynamicLinksCallbacks.Stub callback, String dynamicLink) { + void getDynamicLink(IDynamicLinksCallbacks.Stub callback, @Nullable String dynamicLink) { try { getService().getDynamicLink(callback, dynamicLink); } catch (RemoteException e) { @@ -89,7 +90,11 @@ public int getMinApkVersion() { // or an older version is now supported. Do _not_ use JAR_BUILD_VERSION_CODE as long as this // code is shipped in the 3P SDK (which ships ~from head / dev and would not work with the head // version of the .apk).. - // return BuildConstants.BaseApkVersion.V17; - return 12451000; + return V17; + } + + @Override + public boolean usesClientTelemetry() { + return true; } } diff --git a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/FirebaseDynamicLinkRegistrar.java b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/FirebaseDynamicLinkRegistrar.java index d7fae9ff677..c9bb92041cf 100644 --- a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/FirebaseDynamicLinkRegistrar.java +++ b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/FirebaseDynamicLinkRegistrar.java @@ -1,4 +1,4 @@ -// Copyright 2018 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ package com.google.firebase.dynamiclinks.internal; import androidx.annotation.Keep; +import com.google.android.gms.common.annotation.KeepForSdk; import com.google.firebase.FirebaseApp; import com.google.firebase.analytics.connector.AnalyticsConnector; import com.google.firebase.components.Component; @@ -31,6 +32,7 @@ * * @hide */ +@KeepForSdk @Keep public final class FirebaseDynamicLinkRegistrar implements ComponentRegistrar { @@ -40,11 +42,12 @@ public List> getComponents() { Component firebaseDynamicLinks = Component.builder(FirebaseDynamicLinks.class) .add(Dependency.required(FirebaseApp.class)) - .add(Dependency.optional(AnalyticsConnector.class)) + .add(Dependency.optionalProvider(AnalyticsConnector.class)) .factory( container -> new FirebaseDynamicLinksImpl( - container.get(FirebaseApp.class), container.get(AnalyticsConnector.class))) + container.get(FirebaseApp.class), + container.getProvider(AnalyticsConnector.class))) .build(); // no need for eager init for the Internal component. return Arrays.asList(firebaseDynamicLinks); diff --git a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/FirebaseDynamicLinksImpl.java b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/FirebaseDynamicLinksImpl.java index 4ba77ceb743..d99c756cc2a 100644 --- a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/FirebaseDynamicLinksImpl.java +++ b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/FirebaseDynamicLinksImpl.java @@ -1,4 +1,4 @@ -// Copyright 2018 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,13 +22,14 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; import com.google.android.gms.common.api.Api.ApiOptions.NoOptions; import com.google.android.gms.common.api.GoogleApi; import com.google.android.gms.common.api.Status; import com.google.android.gms.common.api.internal.TaskApiCall; import com.google.android.gms.common.api.internal.TaskUtil; +import com.google.android.gms.common.internal.Preconditions; import com.google.android.gms.common.internal.safeparcel.SafeParcelableSerializer; +import com.google.android.gms.common.util.VisibleForTesting; import com.google.android.gms.tasks.Task; import com.google.android.gms.tasks.TaskCompletionSource; import com.google.android.gms.tasks.Tasks; @@ -39,6 +40,7 @@ import com.google.firebase.dynamiclinks.FirebaseDynamicLinks; import com.google.firebase.dynamiclinks.PendingDynamicLinkData; import com.google.firebase.dynamiclinks.ShortDynamicLink; +import com.google.firebase.inject.Provider; /** * Implementation of FirebaseDynamicLinks that passes requests to the binder interface to gmscore. @@ -57,20 +59,25 @@ public class FirebaseDynamicLinksImpl extends FirebaseDynamicLinks { private final GoogleApi googleApi; - @Nullable private final AnalyticsConnector analytics; + private final Provider analytics; - public FirebaseDynamicLinksImpl(FirebaseApp firebaseApp, @Nullable AnalyticsConnector analytics) { - this(new DynamicLinksApi(firebaseApp.getApplicationContext()), analytics); + private final FirebaseApp firebaseApp; + + public FirebaseDynamicLinksImpl(FirebaseApp firebaseApp, Provider analytics) { + this(new DynamicLinksApi(firebaseApp.getApplicationContext()), firebaseApp, analytics); } // This overload exists to allow injecting a mock GoogleApi instance in tests. @VisibleForTesting public FirebaseDynamicLinksImpl( - GoogleApi googleApi, @Nullable AnalyticsConnector analytics) { + GoogleApi googleApi, + FirebaseApp firebaseApp, + Provider analytics) { this.googleApi = googleApi; + this.firebaseApp = Preconditions.checkNotNull(firebaseApp); this.analytics = analytics; - if (analytics == null) { + if (analytics.get() == null) { // b/34217790: Try to get an instance of Analytics. This initializes Google Analytics // if it is set up for the app, which sets up the association for the app and package name, // allowing GmsCore to log FDL events on behalf of the app. @@ -84,6 +91,11 @@ public FirebaseDynamicLinksImpl( } } + public FirebaseApp getFirebaseApp() { + return firebaseApp; + } + + @Nullable public PendingDynamicLinkData getPendingDynamicLinkData(@NonNull Intent intent) { DynamicLinkData dynamicLinkData = SafeParcelableSerializer.deserializeFromIntentExtra( @@ -120,15 +132,19 @@ public static Uri createDynamicLink(Bundle builderParameters) { if (longLink == null) { // Long link was not supplied, build the Dynamic Link from Dynamic Link parameters. Uri.Builder builder = new Uri.Builder(); - Uri uri = Uri.parse(builderParameters.getString(Builder.KEY_DOMAIN_URI_PREFIX)); + String domainUriPrefix = + Preconditions.checkNotNull(builderParameters.getString(Builder.KEY_DOMAIN_URI_PREFIX)); + Uri uri = Uri.parse(domainUriPrefix); builder.scheme(uri.getScheme()); builder.authority(uri.getAuthority()); builder.path(uri.getPath()); Bundle fdlParameters = builderParameters.getBundle(Builder.KEY_DYNAMIC_LINK_PARAMETERS); - for (String key : fdlParameters.keySet()) { - Object value = fdlParameters.get(key); - if (value != null) { - builder.appendQueryParameter(key, value.toString()); + if (fdlParameters != null) { + for (String key : fdlParameters.keySet()) { + Object value = fdlParameters.get(key); + if (value != null) { + builder.appendQueryParameter(key, value.toString()); + } } } longLink = builder.build(); @@ -153,10 +169,11 @@ public static void verifyDomainUriPrefix(Bundle builderParameters) { static final class GetDynamicLinkImpl extends TaskApiCall { - private final String dynamicLink; - @Nullable private final AnalyticsConnector analytics; + @Nullable private final String dynamicLink; + private final Provider analytics; - GetDynamicLinkImpl(AnalyticsConnector analytics, String dynamicLink) { + GetDynamicLinkImpl(Provider analytics, @Nullable String dynamicLink) { + super(null, false, FirebaseDynamicLinksImplConstants.GET_DYNAMIC_LINK_METHOD_KEY); this.dynamicLink = dynamicLink; this.analytics = analytics; } @@ -176,6 +193,7 @@ static final class CreateShortDynamicLinkImpl private final Bundle builderParameters; CreateShortDynamicLinkImpl(Bundle builderParameters) { + super(null, false, FirebaseDynamicLinksImplConstants.CREATE_SHORT_DYNAMIC_LINK_METHOD_KEY); this.builderParameters = builderParameters; } @@ -192,29 +210,30 @@ protected void doExecute( static class AbstractDynamicLinkCallbacks extends IDynamicLinksCallbacks.Stub { @Override - public void onGetDynamicLink(Status status, DynamicLinkData dynamicLinkData) { + public void onGetDynamicLink(Status status, @Nullable DynamicLinkData dynamicLinkData) { throw new UnsupportedOperationException(); } @Override - public void onCreateShortDynamicLink(Status status, ShortDynamicLinkImpl shortDynamicLink) { + public void onCreateShortDynamicLink( + Status status, @Nullable ShortDynamicLinkImpl shortDynamicLink) { throw new UnsupportedOperationException(); } } static class DynamicLinkCallbacks extends AbstractDynamicLinkCallbacks { private final TaskCompletionSource completionSource; - @Nullable private final AnalyticsConnector analytics; + private final Provider analytics; public DynamicLinkCallbacks( - AnalyticsConnector analytics, + Provider analytics, TaskCompletionSource completionSource) { this.analytics = analytics; this.completionSource = completionSource; } @Override - public void onGetDynamicLink(Status status, DynamicLinkData dynamicLinkData) { + public void onGetDynamicLink(Status status, @Nullable DynamicLinkData dynamicLinkData) { // Send result to client. TaskUtil.setResultOrApiException( status, @@ -230,13 +249,14 @@ public void onGetDynamicLink(Status status, DynamicLinkData dynamicLinkData) { return; } - if (analytics == null) { + AnalyticsConnector connector = analytics.get(); + if (connector == null) { return; } for (String name : scionData.keySet()) { Bundle params = scionData.getBundle(name); - analytics.logEvent(ANALYTICS_FDL_ORIGIN, name, params); + connector.logEvent(ANALYTICS_FDL_ORIGIN, name, params); } } } @@ -249,7 +269,8 @@ static class CreateShortDynamicLinkCallbacks extends AbstractDynamicLinkCallback } @Override - public void onCreateShortDynamicLink(Status status, ShortDynamicLinkImpl shortDynamicLink) { + public void onCreateShortDynamicLink( + Status status, @Nullable ShortDynamicLinkImpl shortDynamicLink) { TaskUtil.setResultOrApiException(status, shortDynamicLink, completionSource); } } diff --git a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/FirebaseDynamicLinksImplConstants.java b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/FirebaseDynamicLinksImplConstants.java new file mode 100644 index 00000000000..c9da60e96b8 --- /dev/null +++ b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/FirebaseDynamicLinksImplConstants.java @@ -0,0 +1,21 @@ +// Copyright 2021 Google LLC +// +// 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. + +/// THIS FILE IS AUTO GENERATED. Do not modify. +package com.google.firebase.dynamiclinks.internal; + +interface FirebaseDynamicLinksImplConstants { + int GET_DYNAMIC_LINK_METHOD_KEY = 13201; + int CREATE_SHORT_DYNAMIC_LINK_METHOD_KEY = 13202; +} diff --git a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/ShortDynamicLinkImpl.java b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/ShortDynamicLinkImpl.java index 87001b8a66d..8a969f3437b 100644 --- a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/ShortDynamicLinkImpl.java +++ b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/ShortDynamicLinkImpl.java @@ -1,4 +1,4 @@ -// Copyright 2018 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,10 +16,11 @@ import android.net.Uri; import android.os.Parcel; +import androidx.annotation.Nullable; import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable; import com.google.android.gms.common.internal.safeparcel.SafeParcelable; import com.google.firebase.dynamiclinks.ShortDynamicLink; -import java.util.Collections; +import java.util.ArrayList; import java.util.List; /** {@link SafeParcelable} implementation of {@link ShortDynamicLink}. */ @@ -29,9 +30,11 @@ public final class ShortDynamicLinkImpl extends AbstractSafeParcelable implement public static final Creator CREATOR = new ShortDynamicLinkImplCreator(); @SafeParcelable.Field(id = 1, getter = "getShortLink") + @Nullable private final Uri shortLink; @SafeParcelable.Field(id = 2, getter = "getPreviewLink") + @Nullable private final Uri previewLink; @SafeParcelable.Field(id = 3, getter = "getWarnings") @@ -39,20 +42,22 @@ public final class ShortDynamicLinkImpl extends AbstractSafeParcelable implement @SafeParcelable.Constructor public ShortDynamicLinkImpl( - @Param(id = 1) Uri shortLink, - @Param(id = 2) Uri previewLink, - @Param(id = 3) List warnings) { + @Nullable @Param(id = 1) Uri shortLink, + @Nullable @Param(id = 2) Uri previewLink, + @Nullable @Param(id = 3) List warnings) { this.shortLink = shortLink; this.previewLink = previewLink; - this.warnings = warnings == null ? Collections.emptyList() : warnings; + this.warnings = warnings == null ? new ArrayList<>() : warnings; } @Override + @Nullable public Uri getShortLink() { return shortLink; } @Override + @Nullable public Uri getPreviewLink() { return previewLink; } @@ -83,6 +88,7 @@ public WarningImpl(@Param(id = 2) String message) { } @Override + @Nullable public String getCode() { // warningCode deprecated on server, returns non-useful, hard-coded value. return null; diff --git a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/ShortDynamicLinkImplCreator.java b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/ShortDynamicLinkImplCreator.java index 7d21232d0a7..8566df1653a 100644 --- a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/ShortDynamicLinkImplCreator.java +++ b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/ShortDynamicLinkImplCreator.java @@ -1,4 +1,4 @@ -// Copyright 2018 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/package-info.java b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/package-info.java index 057fa3bf7f5..1c6d93409f8 100644 --- a/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/package-info.java +++ b/firebase-dynamic-links/src/main/java/com/google/firebase/dynamiclinks/internal/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2018 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/DynamicLinkTest.java b/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/DynamicLinkTest.java index a452b7fd1ab..55ca0f1e62f 100644 --- a/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/DynamicLinkTest.java +++ b/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/DynamicLinkTest.java @@ -14,10 +14,12 @@ package com.google.firebase.dynamiclinks; +import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.net.Uri; import android.os.Bundle; @@ -33,6 +35,7 @@ import com.google.firebase.dynamiclinks.DynamicLink.SocialMetaTagParameters; import com.google.firebase.dynamiclinks.ShortDynamicLink.Suffix; import com.google.firebase.dynamiclinks.internal.FirebaseDynamicLinksImpl; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -103,8 +106,10 @@ public void setUp() { FirebaseApp.clearInstancesForTest(); FirebaseOptions.Builder firebaseOptionsBuilder = new FirebaseOptions.Builder().setApplicationId("application_id").setApiKey(API_KEY); - FirebaseApp.initializeApp( - ApplicationProvider.getApplicationContext(), firebaseOptionsBuilder.build()); + FirebaseApp firebaseApp = + FirebaseApp.initializeApp( + ApplicationProvider.getApplicationContext(), firebaseOptionsBuilder.build()); + when(mockFDLImpl.getFirebaseApp()).thenReturn(firebaseApp); builder = new Builder(mockFDLImpl); builder.setDynamicLinkDomain(DOMAIN); @@ -424,6 +429,20 @@ public void testNavigationInfoParameters_Builder_SetForcedRedirectEnabled_False( assertFalse("1".equals(fdlParameters.get(NavigationInfoParameters.KEY_FORCED_REDIRECT))); } + @Test + public void testSetDynamicLinkDomainDoesNotAcceptCustomDomain() { + IllegalArgumentException e = + Assert.assertThrows( + IllegalArgumentException.class, + () -> { + builder.setDynamicLinkDomain(CUSTOM_DOMAIN_WITHOUT_SCHEME); + }); + assertThat(e.getMessage()) + .isEqualTo( + "Use setDomainUriPrefix() instead, setDynamicLinkDomain() is only applicable for " + + "*.page.link and *.app.goo.gl domains."); + } + /** Gets the Bundle that contains the options used to create the short Dynamic Link. */ private Bundle getParameterBundle() { builder.buildShortDynamicLink(); diff --git a/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/FirebaseDynamicLinksTest.java b/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/FirebaseDynamicLinksTest.java new file mode 100644 index 00000000000..4059c2348cf --- /dev/null +++ b/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/FirebaseDynamicLinksTest.java @@ -0,0 +1,45 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.firebase.dynamiclinks; + +import static junit.framework.Assert.assertNotNull; + +import androidx.test.core.app.ApplicationProvider; +import com.google.firebase.FirebaseApp; +import com.google.firebase.FirebaseOptions; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class FirebaseDynamicLinksTest { + + @Before + public void setUp() { + FirebaseOptions.Builder firebaseOptionsBuilder = + new FirebaseOptions.Builder().setApplicationId("application_id").setApiKey("api_key"); + FirebaseApp.initializeApp( + ApplicationProvider.getApplicationContext(), firebaseOptionsBuilder.build()); + } + + @Test + @Ignore + public void testFirebaseDynamicLinks_GetInstance() { + FirebaseDynamicLinks firebaseDynamicLinks = FirebaseDynamicLinks.getInstance(); + assertNotNull(firebaseDynamicLinks); + } +} diff --git a/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/internal/AnalyticsValidator.java b/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/internal/AnalyticsValidator.java new file mode 100644 index 00000000000..efa217c643f --- /dev/null +++ b/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/internal/AnalyticsValidator.java @@ -0,0 +1,56 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.firebase.dynamiclinks.internal; + +import android.os.Bundle; +import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableList; +import com.google.firebase.analytics.connector.AnalyticsConnector.ConditionalUserProperty; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; + +/** A validator for checking that the Analytics events and properties are set properly. */ +public interface AnalyticsValidator { + + /** A representation of a Analytics Event for validation purposes. */ + @AutoValue + public abstract static class LoggedEvent { + public static LoggedEvent create(String origin, String name, Bundle params) { + return new AutoValue_AnalyticsValidator_LoggedEvent(origin, name, params); + } + + public abstract String getOrigin(); + + public abstract String getName(); + + @Nullable + public abstract Bundle getParams(); + } + + /** Resets the saved data between test cases. */ + void reset(); + + /** Returns all events that have been logged in the order that they were logged. */ + ImmutableList getLoggedEvents(); + + /** Returns all event names that have been logged in the order that they were logged. */ + ImmutableList getLoggedEventNames(); + + /** Returns all user properties that have been set without order. */ + Map getUserProperties(boolean includeInternal); + + /** Returns all conditional user properties that have been set in the order that they were set. */ + List getConditionalUserProperties(); +} diff --git a/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/internal/FakeAnalyticsConnector.java b/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/internal/FakeAnalyticsConnector.java new file mode 100644 index 00000000000..3e78d27cab8 --- /dev/null +++ b/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/internal/FakeAnalyticsConnector.java @@ -0,0 +1,132 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.firebase.dynamiclinks.internal; + +import android.os.Bundle; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.firebase.analytics.connector.AnalyticsConnector; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * A fast, deterministic, fake implementation of AnalyticsConnector to be used for unit testing. + * + *

It provides support for logging events, setting/getting user properties, and setting/getting + * conditional user properties. + */ +public class FakeAnalyticsConnector implements AnalyticsConnector, AnalyticsValidator { + + private static final String CAMPAIGN_INFO_SOURCE = "_cis"; + private static final String FCM_CONNECTOR_CAMPAIGN = "fcm_integration"; + private final List events = new ArrayList<>(); + private final Map userProperties = new HashMap<>(); + private final List conditionalUserProperties = new ArrayList<>(); + + @Override + public AnalyticsConnectorHandle registerAnalyticsConnectorListener( + String origin, AnalyticsConnectorListener listener) { + return null; + } + + @Override + public void logEvent(String origin, String name, Bundle params) { + if (origin.equals("fcm")) { + params.putString(CAMPAIGN_INFO_SOURCE, FCM_CONNECTOR_CAMPAIGN); + } + events.add(AnalyticsValidator.LoggedEvent.create(origin, name, params)); + } + + @Override + public void setUserProperty(String origin, String name, Object value) { + userProperties.put(name, value); + } + + @Override + public Map getUserProperties(boolean includeInternal) { + ImmutableMap.Builder filteredProperties = ImmutableMap.builder(); + for (Entry property : userProperties.entrySet()) { + if (includeInternal || !property.getKey().startsWith("_")) { + filteredProperties.put(property); + } + } + return filteredProperties.build(); + } + + @Override + public void setConditionalUserProperty(ConditionalUserProperty conditionalUserProperty) { + conditionalUserProperties.add(conditionalUserProperty); + } + + @Override + public void clearConditionalUserProperty( + String userPropertyName, String clearEventName, Bundle clearEventParams) { + for (Iterator iterator = conditionalUserProperties.iterator(); + iterator.hasNext(); ) { + ConditionalUserProperty conditionalUserProperty = iterator.next(); + if (conditionalUserProperty.name.equals(userPropertyName)) { + iterator.remove(); + logEvent(conditionalUserProperty.origin, clearEventName, clearEventParams); + } + } + } + + @Override + public int getMaxUserProperties(String origin) { + return 25; + } + + @Override + public List getConditionalUserProperties( + String origin, String propertyNamePrefix) { + ImmutableList.Builder filteredProperties = ImmutableList.builder(); + for (ConditionalUserProperty property : conditionalUserProperties) { + if (property.origin.equals(origin) && property.name.startsWith(propertyNamePrefix)) { + filteredProperties.add(property); + } + } + return filteredProperties.build(); + } + + @Override + public List getConditionalUserProperties() { + return conditionalUserProperties; + } + + @Override + public ImmutableList getLoggedEvents() { + return ImmutableList.copyOf(events); + } + + @Override + public ImmutableList getLoggedEventNames() { + ImmutableList.Builder names = ImmutableList.builder(); + for (AnalyticsValidator.LoggedEvent event : events) { + names.add(event.getName()); + } + return names.build(); + } + + @Override + public void reset() { + events.clear(); + userProperties.clear(); + conditionalUserProperties.clear(); + } +} diff --git a/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/internal/FakeConnectorComponent.java b/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/internal/FakeConnectorComponent.java new file mode 100644 index 00000000000..e9ce91f14e7 --- /dev/null +++ b/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/internal/FakeConnectorComponent.java @@ -0,0 +1,53 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.firebase.dynamiclinks.internal; + +import com.google.firebase.analytics.connector.AnalyticsConnector; +import com.google.firebase.components.Component; +import com.google.firebase.components.ComponentRegistrar; +import java.util.Arrays; +import java.util.List; + +/** + * A component that injects a FakeAnalyticsConnector. + * + *

The FakeAnalyticsConnector should be used in open source testing to validate interactions with + * the AnalyticsConnector. Use getAnalyticsValidator() for validating. + */ +public final class FakeConnectorComponent implements ComponentRegistrar { + + private static final FakeAnalyticsConnector analyticsConnector = new FakeAnalyticsConnector(); + + @Override + public List> getComponents() { + Component connector = + Component.builder(AnalyticsConnector.class) + .factory(container -> analyticsConnector) + .build(); + return Arrays.asList(connector); + } + + /** + * Returns an AnalyticsValidator that can be used to validate interactions with the + * FakeAnalyticsConnector. + */ + public static AnalyticsValidator getAnalyticsValidator() { + return analyticsConnector; + } + + /** Provides access to an instance of AnalyticsConnector. */ + public static AnalyticsConnector getAnalyticsConnector() { + return analyticsConnector; + } +} diff --git a/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/internal/FirebaseDynamicLinksImplTest.java b/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/internal/FirebaseDynamicLinksImplTest.java index 561cddad904..dabb358e9a8 100644 --- a/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/internal/FirebaseDynamicLinksImplTest.java +++ b/firebase-dynamic-links/src/test/java/com/google/firebase/dynamiclinks/internal/FirebaseDynamicLinksImplTest.java @@ -40,6 +40,7 @@ import com.google.firebase.dynamiclinks.PendingDynamicLinkData; import com.google.firebase.dynamiclinks.ShortDynamicLink; import com.google.firebase.dynamiclinks.internal.FirebaseDynamicLinksImpl.CreateShortDynamicLinkImpl; +import com.google.firebase.inject.Provider; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -72,7 +73,11 @@ public class FirebaseDynamicLinksImplTest { private static final String ANALYTICS_FDL_ORIGIN = "fdl"; - @Mock private AnalyticsConnector mockAnalytics; + private final AnalyticsValidator fakeAppMeasurement = + FakeConnectorComponent.getAnalyticsValidator(); + private final Provider mockAnalytics = + FakeConnectorComponent::getAnalyticsConnector; + @Mock private DynamicLinksApi mockGoogleApi; @Mock private TaskCompletionSource mockCompletionSource; @Mock private TaskCompletionSource mockShortFDLCompletionSource; @@ -90,6 +95,7 @@ private static Bundle createDynamicLinkBundle() { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); + fakeAppMeasurement.reset(); FirebaseApp.clearInstancesForTest(); FirebaseOptions.Builder firebaseOptionsBuilder = new FirebaseOptions.Builder().setApplicationId("application_id").setApiKey("api_key"); @@ -102,7 +108,7 @@ public void setUp() throws Exception { .buildUpon() .appendQueryParameter("url", "http://example.google.com") .build(); - api = new FirebaseDynamicLinksImpl(mockGoogleApi, mockAnalytics); + api = new FirebaseDynamicLinksImpl(mockGoogleApi, firebaseApp, mockAnalytics); } @Test @@ -195,6 +201,10 @@ public void testDynamicLinkCallbacks_onGetDynamicLink() { DynamicLinkData data = genDynamicLinkData(scionParams); callbacks.onGetDynamicLink(Status.RESULT_SUCCESS, data); verify(mockCompletionSource).setResult(any(PendingDynamicLinkData.class)); + AnalyticsValidator.LoggedEvent event = fakeAppMeasurement.getLoggedEvents().get(0); + assertEquals(ANALYTICS_FDL_ORIGIN, event.getOrigin()); + assertEquals(SCION_EVENT_NAME, event.getName()); + assertEquals(scionParams, event.getParams()); } @Test @@ -202,7 +212,7 @@ public void testDynamicLinkCallbacks_onGetDynamicLink_missingAnalytics() { // Make sure that a result is returned even if scion is not linked. FirebaseDynamicLinksImpl.DynamicLinkCallbacks callbacks = new FirebaseDynamicLinksImpl.DynamicLinkCallbacks( - /* analytics= */ null, mockCompletionSource); + /* analytics= */ () -> null, mockCompletionSource); DynamicLinkData data = genDynamicLinkData(new Bundle()); callbacks.onGetDynamicLink(Status.RESULT_SUCCESS, data); verify(mockCompletionSource).setResult(any(PendingDynamicLinkData.class));