From 8bb64d9dd9ef96c113339ad1179df1b3b4c21fba Mon Sep 17 00:00:00 2001 From: yashjain2 Date: Tue, 25 Apr 2023 02:21:56 +0530 Subject: [PATCH 1/2] Added FCM root URL in FirebaseOptions --- .../com/google/firebase/FirebaseOptions.java | 31 ++++++++++++++ .../FirebaseMessagingClientImpl.java | 41 ++++++++++++------- .../google/firebase/FirebaseOptionsTest.java | 5 +++ .../FirebaseMessagingClientImplTest.java | 4 +- 4 files changed, 66 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/google/firebase/FirebaseOptions.java b/src/main/java/com/google/firebase/FirebaseOptions.java index 8e7a29ccb..a2c21c3d4 100644 --- a/src/main/java/com/google/firebase/FirebaseOptions.java +++ b/src/main/java/com/google/firebase/FirebaseOptions.java @@ -74,6 +74,7 @@ public GoogleCredentials get() { }; private final String databaseUrl; + private final String fcmRootUrl; private final String storageBucket; private final Supplier credentialsSupplier; private final Map databaseAuthVariableOverride; @@ -101,6 +102,11 @@ private FirebaseOptions(@NonNull final FirebaseOptions.Builder builder) { } else { this.serviceAccountId = null; } + if (!Strings.isNullOrEmpty(builder.fcmRootUrl)) { + this.fcmRootUrl = builder.fcmRootUrl; + } else { + this.fcmRootUrl = null; + } this.storageBucket = builder.storageBucket; this.httpTransport = builder.httpTransport != null ? builder.httpTransport : ApiClientUtils.getDefaultTransport(); @@ -124,6 +130,15 @@ public String getDatabaseUrl() { return databaseUrl; } + /** + * Returns the Fcm Root URL that is used for Fcm Messaging. + * + * @return The Fcm Messaging URL supplied via {@link Builder#setFcmRootUrl}. + */ + public String getFcmRootUrl() { + return fcmRootUrl; + } + /** * Returns the name of the Google Cloud Storage bucket used for storing application data. * @@ -260,6 +275,7 @@ public static final class Builder { private ThreadManager threadManager; private int connectTimeout; private int readTimeout; + private String fcmRootUrl; /** * Constructs an empty builder. @@ -290,6 +306,7 @@ public Builder(FirebaseOptions options) { connectTimeout = options.connectTimeout; readTimeout = options.readTimeout; firestoreOptions = options.firestoreOptions; + fcmRootUrl = options.fcmRootUrl; } /** @@ -306,6 +323,20 @@ public Builder setDatabaseUrl(@Nullable String databaseUrl) { return this; } + /** + * Sets the Fcm Root URL to use for Fcm Messaging. + * + *

See + * Initialize the SDK for code samples and detailed documentation. + * + * @param fcmRootUrl The Fcm Root URL to use for Fcm Messaging. + * @return This Builder instance is returned so subsequent calls can be chained. + */ + public Builder setFcmRootUrl(@Nullable String fcmRootUrl) { + this.fcmRootUrl = fcmRootUrl; + return this; + } + /** * Sets the name of the Google Cloud Storage bucket for reading and writing application data. * This should be the full name of the bucket as listed in the diff --git a/src/main/java/com/google/firebase/messaging/FirebaseMessagingClientImpl.java b/src/main/java/com/google/firebase/messaging/FirebaseMessagingClientImpl.java index 1271bf98b..1806eb446 100644 --- a/src/main/java/com/google/firebase/messaging/FirebaseMessagingClientImpl.java +++ b/src/main/java/com/google/firebase/messaging/FirebaseMessagingClientImpl.java @@ -59,8 +59,9 @@ * A helper class for interacting with Firebase Cloud Messaging service. */ final class FirebaseMessagingClientImpl implements FirebaseMessagingClient { - - private static final String FCM_URL = "https://fcm.googleapis.com/v1/projects/%s/messages:send"; + private static final String FCM_ROOT_URL = "https://fcm.googleapis.com"; + private static final String FCM_SEND_PATH = "v1/projects/%s/messages:send"; + private static final String FCM_BATCH_PATH = "batch"; private static final Map COMMON_HEADERS = ImmutableMap.of( @@ -68,6 +69,7 @@ final class FirebaseMessagingClientImpl implements FirebaseMessagingClient { "X-Firebase-Client", "fire-admin-java/" + SdkUtils.getVersion()); private final String fcmSendUrl; + private final String fcmBatchUrl; private final HttpRequestFactory requestFactory; private final HttpRequestFactory childRequestFactory; private final JsonFactory jsonFactory; @@ -78,7 +80,11 @@ final class FirebaseMessagingClientImpl implements FirebaseMessagingClient { private FirebaseMessagingClientImpl(Builder builder) { checkArgument(!Strings.isNullOrEmpty(builder.projectId)); - this.fcmSendUrl = String.format(FCM_URL, builder.projectId); + String fcmRootUrl = Strings.isNullOrEmpty(builder.fcmRootUrl) ? FCM_ROOT_URL : builder.fcmRootUrl; + this.fcmSendUrl = String.format(String.format( + "%s/%s", fcmRootUrl, FCM_SEND_PATH), + builder.projectId); + this.fcmBatchUrl = String.format("%s/%s", fcmRootUrl, FCM_BATCH_PATH); this.requestFactory = checkNotNull(builder.requestFactory); this.childRequestFactory = checkNotNull(builder.childRequestFactory); this.jsonFactory = checkNotNull(builder.jsonFactory); @@ -86,7 +92,7 @@ private FirebaseMessagingClientImpl(Builder builder) { this.errorHandler = new MessagingErrorHandler(this.jsonFactory); this.httpClient = new ErrorHandlingHttpClient<>(requestFactory, jsonFactory, errorHandler) .setInterceptor(responseInterceptor); - this.batchClient = new MessagingBatchClient(requestFactory.getTransport(), jsonFactory); + this.batchClient = new MessagingBatchClient(requestFactory.getTransport(), jsonFactory, fcmRootUrl); } @VisibleForTesting @@ -94,6 +100,11 @@ String getFcmSendUrl() { return fcmSendUrl; } + @VisibleForTesting + String getFcmBatchUrl() { + return fcmBatchUrl; + } + @VisibleForTesting HttpRequestFactory getRequestFactory() { return requestFactory; @@ -139,7 +150,7 @@ private BatchResponse sendBatchRequest( return new BatchResponseImpl(callback.getResponses()); } catch (HttpResponseException e) { OutgoingHttpRequest req = new OutgoingHttpRequest( - HttpMethods.POST, MessagingBatchClient.FCM_BATCH_URL); + HttpMethods.POST, fcmBatchUrl); IncomingHttpResponse resp = new IncomingHttpResponse(e, req); throw errorHandler.handleHttpResponseException(e, resp); } catch (IOException e) { @@ -193,6 +204,7 @@ static FirebaseMessagingClientImpl fromApp(FirebaseApp app) { .setRequestFactory(ApiClientUtils.newAuthorizedRequestFactory(app)) .setChildRequestFactory(ApiClientUtils.newUnauthorizedRequestFactory(app)) .setJsonFactory(app.getOptions().getJsonFactory()) + .setFcmRootUrl(app.getOptions().getFcmRootUrl()) .build(); } @@ -207,9 +219,15 @@ static final class Builder { private HttpRequestFactory childRequestFactory; private JsonFactory jsonFactory; private HttpResponseInterceptor responseInterceptor; + private String fcmRootUrl; private Builder() { } + Builder setFcmRootUrl(String fcmRootUrl) { + this.fcmRootUrl = fcmRootUrl; + return this; + } + Builder setProjectId(String projectId) { this.projectId = projectId; return this; @@ -319,13 +337,8 @@ private MessagingServiceErrorResponse safeParse(String response) { private static class MessagingBatchClient extends AbstractGoogleJsonClient { - private static final String FCM_ROOT_URL = "https://fcm.googleapis.com"; - private static final String FCM_BATCH_PATH = "batch"; - private static final String FCM_BATCH_URL = String.format( - "%s/%s", FCM_ROOT_URL, FCM_BATCH_PATH); - - MessagingBatchClient(HttpTransport transport, JsonFactory jsonFactory) { - super(new Builder(transport, jsonFactory)); + MessagingBatchClient(HttpTransport transport, JsonFactory jsonFactory, String fcmRootUrl) { + super(new Builder(transport, jsonFactory, fcmRootUrl)); } private MessagingBatchClient(Builder builder) { @@ -333,8 +346,8 @@ private MessagingBatchClient(Builder builder) { } private static class Builder extends AbstractGoogleJsonClient.Builder { - Builder(HttpTransport transport, JsonFactory jsonFactory) { - super(transport, jsonFactory, FCM_ROOT_URL, "", null, false); + Builder(HttpTransport transport, JsonFactory jsonFactory, String fcmRootUrl) { + super(transport, jsonFactory, fcmRootUrl, "", null, false); setBatchPath(FCM_BATCH_PATH); setApplicationName("fire-admin-java"); } diff --git a/src/test/java/com/google/firebase/FirebaseOptionsTest.java b/src/test/java/com/google/firebase/FirebaseOptionsTest.java index c74215beb..493296117 100644 --- a/src/test/java/com/google/firebase/FirebaseOptionsTest.java +++ b/src/test/java/com/google/firebase/FirebaseOptionsTest.java @@ -44,6 +44,7 @@ public class FirebaseOptionsTest { private static final String FIREBASE_DB_URL = "https://mock-project.firebaseio.com"; + private static final String FIREBASE_FCM_URL = "https://localhost"; private static final String FIREBASE_STORAGE_BUCKET = "mock-storage-bucket"; private static final String FIREBASE_PROJECT_ID = "explicit-project-id"; @@ -53,6 +54,7 @@ public class FirebaseOptionsTest { .setStorageBucket(FIREBASE_STORAGE_BUCKET) .setProjectId(FIREBASE_PROJECT_ID) .setCredentials(TestUtils.getCertCredential(ServiceAccount.EDITOR.asStream())) + .setFcmRootUrl(FIREBASE_FCM_URL) .build(); private static final ThreadManager MOCK_THREAD_MANAGER = new ThreadManager() { @@ -88,8 +90,10 @@ public void createOptionsWithAllValuesSet() throws IOException { .setConnectTimeout(30000) .setReadTimeout(60000) .setFirestoreOptions(firestoreOptions) + .setFcmRootUrl(FIREBASE_FCM_URL) .build(); assertEquals(FIREBASE_DB_URL, firebaseOptions.getDatabaseUrl()); + assertEquals(FIREBASE_FCM_URL, firebaseOptions.getFcmRootUrl()); assertEquals(FIREBASE_STORAGE_BUCKET, firebaseOptions.getStorageBucket()); assertEquals(FIREBASE_PROJECT_ID, firebaseOptions.getProjectId()); assertSame(jsonFactory, firebaseOptions.getJsonFactory()); @@ -183,6 +187,7 @@ public void checkToBuilderCreatesNewEquivalentInstance() { assertNotSame(ALL_VALUES_OPTIONS, allValuesOptionsCopy); assertEquals(ALL_VALUES_OPTIONS.getCredentials(), allValuesOptionsCopy.getCredentials()); assertEquals(ALL_VALUES_OPTIONS.getDatabaseUrl(), allValuesOptionsCopy.getDatabaseUrl()); + assertEquals(ALL_VALUES_OPTIONS.getFcmRootUrl(), allValuesOptionsCopy.getFcmRootUrl()); assertEquals(ALL_VALUES_OPTIONS.getProjectId(), allValuesOptionsCopy.getProjectId()); assertEquals(ALL_VALUES_OPTIONS.getJsonFactory(), allValuesOptionsCopy.getJsonFactory()); assertEquals(ALL_VALUES_OPTIONS.getHttpTransport(), allValuesOptionsCopy.getHttpTransport()); diff --git a/src/test/java/com/google/firebase/messaging/FirebaseMessagingClientImplTest.java b/src/test/java/com/google/firebase/messaging/FirebaseMessagingClientImplTest.java index 17848cc65..f4f126952 100644 --- a/src/test/java/com/google/firebase/messaging/FirebaseMessagingClientImplTest.java +++ b/src/test/java/com/google/firebase/messaging/FirebaseMessagingClientImplTest.java @@ -62,7 +62,8 @@ public class FirebaseMessagingClientImplTest { private static final String TEST_FCM_URL = - "https://fcm.googleapis.com/v1/projects/test-project/messages:send"; + "https://fcm.googleapis.com/v1/projects/test-project/messages:send"; + private static final String TEST_FCM_BATCH_URL = "https://fcm.googleapis.com/batch"; private static final List HTTP_ERRORS = ImmutableList.of(401, 404, 500); @@ -534,6 +535,7 @@ public void testFromApp() throws IOException { FirebaseMessagingClientImpl client = FirebaseMessagingClientImpl.fromApp(app); assertEquals(TEST_FCM_URL, client.getFcmSendUrl()); + assertEquals(TEST_FCM_BATCH_URL, client.getFcmBatchUrl()); assertSame(options.getJsonFactory(), client.getJsonFactory()); HttpRequest request = client.getRequestFactory().buildGetRequest( From e7ecff3d618dba49eec2f2b26acf8dc7de5d9126 Mon Sep 17 00:00:00 2001 From: yashjain2 Date: Thu, 8 Jun 2023 23:15:56 +0530 Subject: [PATCH 2/2] Refactored --- .../firebase/messaging/FirebaseMessagingClientImpl.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/google/firebase/messaging/FirebaseMessagingClientImpl.java b/src/main/java/com/google/firebase/messaging/FirebaseMessagingClientImpl.java index 1806eb446..1015b71b4 100644 --- a/src/main/java/com/google/firebase/messaging/FirebaseMessagingClientImpl.java +++ b/src/main/java/com/google/firebase/messaging/FirebaseMessagingClientImpl.java @@ -80,7 +80,8 @@ final class FirebaseMessagingClientImpl implements FirebaseMessagingClient { private FirebaseMessagingClientImpl(Builder builder) { checkArgument(!Strings.isNullOrEmpty(builder.projectId)); - String fcmRootUrl = Strings.isNullOrEmpty(builder.fcmRootUrl) ? FCM_ROOT_URL : builder.fcmRootUrl; + String fcmRootUrl = Strings.isNullOrEmpty(builder.fcmRootUrl) ? FCM_ROOT_URL : + builder.fcmRootUrl; this.fcmSendUrl = String.format(String.format( "%s/%s", fcmRootUrl, FCM_SEND_PATH), builder.projectId); @@ -92,7 +93,8 @@ private FirebaseMessagingClientImpl(Builder builder) { this.errorHandler = new MessagingErrorHandler(this.jsonFactory); this.httpClient = new ErrorHandlingHttpClient<>(requestFactory, jsonFactory, errorHandler) .setInterceptor(responseInterceptor); - this.batchClient = new MessagingBatchClient(requestFactory.getTransport(), jsonFactory, fcmRootUrl); + this.batchClient = new MessagingBatchClient(requestFactory.getTransport(), + jsonFactory, fcmRootUrl); } @VisibleForTesting