Skip to content

Commit 8620216

Browse files
authored
Use dagger in functions. (#4366)
This simplifies injection of firebase components so they don't have to be passed all the way from the registrar into classes that actually use components. This change adds `+4.22 kB` to the size of the sdk, but is a small enough increase compared to the advantages it provides
1 parent 7b13cd7 commit 8620216

File tree

9 files changed

+127
-65
lines changed

9 files changed

+127
-65
lines changed

firebase-functions/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Unreleased
22
* [changed] Avoid executing code on the UI thread as much as possible.
3+
* [changed] Internal infrastructure improvements.
34

45
# 20.2.1
56
* [changed] Updated dependency of `firebase-iid` to its latest

firebase-functions/firebase-functions.gradle

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
plugins {
1616
id 'firebase-library'
17+
id 'firebase-vendor'
1718
}
1819

1920
firebaseLibrary {
@@ -68,6 +69,12 @@ dependencies {
6869

6970
implementation 'com.squareup.okhttp3:okhttp:3.12.1'
7071

72+
implementation 'javax.inject:javax.inject:1'
73+
vendor ('com.google.dagger:dagger:2.43.2') {
74+
exclude group: "javax.inject", module: "javax.inject"
75+
}
76+
annotationProcessor 'com.google.dagger:dagger-compiler:2.43.2'
77+
7178
annotationProcessor 'com.google.auto.value:auto-value:1.6.2'
7279

7380
javadocClasspath 'com.google.code.findbugs:jsr305:3.0.2'

firebase-functions/src/androidTest/java/com/google/firebase/functions/CallTest.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ public void testToken() throws InterruptedException, ExecutionException {
8585
// Override the normal token provider to simulate FirebaseAuth being logged in.
8686
FirebaseFunctions functions =
8787
new FirebaseFunctions(
88-
app,
8988
app.getApplicationContext(),
9089
app.getOptions().getProjectId(),
9190
"us-central1",
@@ -108,7 +107,6 @@ public void testInstanceId() throws InterruptedException, ExecutionException {
108107
// Override the normal token provider to simulate FirebaseAuth being logged in.
109108
FirebaseFunctions functions =
110109
new FirebaseFunctions(
111-
app,
112110
app.getApplicationContext(),
113111
app.getOptions().getProjectId(),
114112
"us-central1",
@@ -131,7 +129,6 @@ public void testAppCheck() throws InterruptedException, ExecutionException {
131129
// Override the normal token provider to simulate FirebaseAuth being logged in.
132130
FirebaseFunctions functions =
133131
new FirebaseFunctions(
134-
app,
135132
app.getApplicationContext(),
136133
app.getOptions().getProjectId(),
137134
"us-central1",

firebase-functions/src/main/java/com/google/firebase/functions/FirebaseContextProvider.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@
2626
import com.google.firebase.internal.api.FirebaseNoSignedInUserException;
2727
import java.util.concurrent.Executor;
2828
import java.util.concurrent.atomic.AtomicReference;
29+
import javax.inject.Inject;
30+
import javax.inject.Singleton;
2931

3032
/** A ContextProvider that uses FirebaseAuth to get the token. */
33+
@Singleton
3134
class FirebaseContextProvider implements ContextProvider {
3235
private final String TAG = "FirebaseContextProvider";
3336

@@ -37,6 +40,7 @@ class FirebaseContextProvider implements ContextProvider {
3740
new AtomicReference<>();
3841
private final Executor executor;
3942

43+
@Inject
4044
FirebaseContextProvider(
4145
Provider<InternalAuthProvider> tokenProvider,
4246
Provider<FirebaseInstanceIdInternal> instanceId,

firebase-functions/src/main/java/com/google/firebase/functions/FirebaseFunctions.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,16 @@
3030
import com.google.firebase.annotations.concurrent.UiThread;
3131
import com.google.firebase.emulators.EmulatedServiceSettings;
3232
import com.google.firebase.functions.FirebaseFunctionsException.Code;
33+
import dagger.assisted.Assisted;
34+
import dagger.assisted.AssistedInject;
3335
import java.io.IOException;
3436
import java.io.InterruptedIOException;
3537
import java.net.MalformedURLException;
3638
import java.net.URL;
3739
import java.util.HashMap;
3840
import java.util.Map;
3941
import java.util.concurrent.Executor;
42+
import javax.inject.Named;
4043
import okhttp3.Call;
4144
import okhttp3.Callback;
4245
import okhttp3.MediaType;
@@ -59,9 +62,6 @@ public class FirebaseFunctions {
5962
*/
6063
private static boolean providerInstallStarted = false;
6164

62-
// The FirebaseApp instance
63-
private final FirebaseApp app;
64-
6565
// The network client to use for HTTPS requests.
6666
private final OkHttpClient client;
6767

@@ -88,15 +88,14 @@ public class FirebaseFunctions {
8888
// Emulator settings
8989
@Nullable private EmulatedServiceSettings emulatorSettings;
9090

91+
@AssistedInject
9192
FirebaseFunctions(
92-
FirebaseApp app,
9393
Context context,
94-
String projectId,
95-
String regionOrCustomDomain,
94+
@Named("projectId") String projectId,
95+
@Assisted String regionOrCustomDomain,
9696
ContextProvider contextProvider,
9797
@Lightweight Executor executor,
9898
@UiThread Executor uiExecutor) {
99-
this.app = app;
10099
this.executor = executor;
101100
this.client = new OkHttpClient();
102101
this.serializer = new Serializer();
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright 2018 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.functions;
16+
17+
import android.content.Context;
18+
import com.google.firebase.FirebaseOptions;
19+
import com.google.firebase.annotations.concurrent.Lightweight;
20+
import com.google.firebase.annotations.concurrent.UiThread;
21+
import com.google.firebase.appcheck.interop.InternalAppCheckTokenProvider;
22+
import com.google.firebase.auth.internal.InternalAuthProvider;
23+
import com.google.firebase.iid.internal.FirebaseInstanceIdInternal;
24+
import com.google.firebase.inject.Deferred;
25+
import com.google.firebase.inject.Provider;
26+
import dagger.Binds;
27+
import dagger.BindsInstance;
28+
import dagger.Component;
29+
import dagger.Module;
30+
import dagger.Provides;
31+
import java.util.concurrent.Executor;
32+
import javax.inject.Named;
33+
import javax.inject.Singleton;
34+
35+
/** @hide */
36+
@Component(modules = FunctionsComponent.MainModule.class)
37+
@Singleton
38+
interface FunctionsComponent {
39+
FunctionsMultiResourceComponent getMultiResourceComponent();
40+
41+
@Component.Builder
42+
interface Builder {
43+
@BindsInstance
44+
Builder setApplicationContext(Context applicationContext);
45+
46+
@BindsInstance
47+
Builder setFirebaseOptions(FirebaseOptions options);
48+
49+
@BindsInstance
50+
Builder setLiteExecutor(@Lightweight Executor executor);
51+
52+
@BindsInstance
53+
Builder setUiExecutor(@UiThread Executor executor);
54+
55+
@BindsInstance
56+
Builder setAuth(Provider<InternalAuthProvider> auth);
57+
58+
@BindsInstance
59+
Builder setIid(Provider<FirebaseInstanceIdInternal> iid);
60+
61+
@BindsInstance
62+
Builder setAppCheck(Deferred<InternalAppCheckTokenProvider> appCheck);
63+
64+
FunctionsComponent build();
65+
}
66+
67+
@Module
68+
interface MainModule {
69+
@Provides
70+
@Named("projectId")
71+
static String bindProjectId(FirebaseOptions options) {
72+
return options.getProjectId();
73+
}
74+
75+
@Binds
76+
ContextProvider contextProvider(FirebaseContextProvider provider);
77+
}
78+
}

firebase-functions/src/main/java/com/google/firebase/functions/FunctionsMultiResourceComponent.java

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@
1414

1515
package com.google.firebase.functions;
1616

17-
import android.content.Context;
1817
import androidx.annotation.GuardedBy;
19-
import androidx.annotation.UiThread;
20-
import com.google.firebase.FirebaseApp;
21-
import com.google.firebase.annotations.concurrent.Lightweight;
18+
import dagger.assisted.Assisted;
19+
import dagger.assisted.AssistedFactory;
2220
import java.util.HashMap;
2321
import java.util.Map;
24-
import java.util.concurrent.Executor;
22+
import javax.inject.Inject;
23+
import javax.inject.Singleton;
2524

2625
/** Multi-resource container for Functions. */
26+
@Singleton
2727
class FunctionsMultiResourceComponent {
2828
/**
2929
* A static map from instance key to FirebaseFunctions instances. Instance keys region names.
@@ -33,41 +33,24 @@ class FunctionsMultiResourceComponent {
3333
@GuardedBy("this")
3434
private final Map<String, FirebaseFunctions> instances = new HashMap<>();
3535

36-
private final Context applicationContext;
37-
private final ContextProvider contextProvider;
38-
private final FirebaseApp app;
39-
private final Executor liteExecutor;
40-
private final Executor uiExecutor;
36+
private final FirebaseFunctionsFactory functionsFactory;
4137

42-
FunctionsMultiResourceComponent(
43-
Context applicationContext,
44-
ContextProvider contextProvider,
45-
FirebaseApp app,
46-
@Lightweight Executor liteExecutor,
47-
@UiThread Executor uiExecutor) {
48-
this.applicationContext = applicationContext;
49-
this.contextProvider = contextProvider;
50-
this.app = app;
51-
this.liteExecutor = liteExecutor;
52-
this.uiExecutor = uiExecutor;
38+
@Inject
39+
FunctionsMultiResourceComponent(FirebaseFunctionsFactory functionsFactory) {
40+
this.functionsFactory = functionsFactory;
5341
}
5442

5543
synchronized FirebaseFunctions get(String regionOrCustomDomain) {
5644
FirebaseFunctions functions = instances.get(regionOrCustomDomain);
57-
String projectId = app.getOptions().getProjectId();
58-
5945
if (functions == null) {
60-
functions =
61-
new FirebaseFunctions(
62-
app,
63-
applicationContext,
64-
projectId,
65-
regionOrCustomDomain,
66-
contextProvider,
67-
liteExecutor,
68-
uiExecutor);
46+
functions = functionsFactory.create(regionOrCustomDomain);
6947
instances.put(regionOrCustomDomain, functions);
7048
}
7149
return functions;
7250
}
51+
52+
@AssistedFactory
53+
interface FirebaseFunctionsFactory {
54+
FirebaseFunctions create(@Assisted String regionOrCustomDomain);
55+
}
7356
}

firebase-functions/src/main/java/com/google/firebase/functions/FunctionsRegistrar.java

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import android.content.Context;
1818
import androidx.annotation.Keep;
19-
import com.google.firebase.FirebaseApp;
19+
import com.google.firebase.FirebaseOptions;
2020
import com.google.firebase.annotations.concurrent.Lightweight;
2121
import com.google.firebase.annotations.concurrent.UiThread;
2222
import com.google.firebase.appcheck.interop.InternalAppCheckTokenProvider;
@@ -45,34 +45,27 @@ public List<Component<?>> getComponents() {
4545
Qualified<Executor> liteExecutor = Qualified.qualified(Lightweight.class, Executor.class);
4646
Qualified<Executor> uiExecutor = Qualified.qualified(UiThread.class, Executor.class);
4747
return Arrays.asList(
48-
Component.builder(ContextProvider.class)
49-
.add(Dependency.optionalProvider(InternalAuthProvider.class))
50-
.add(Dependency.requiredProvider(FirebaseInstanceIdInternal.class))
51-
.add(Dependency.deferred(InternalAppCheckTokenProvider.class))
52-
.add(Dependency.required(liteExecutor))
53-
.factory(
54-
c ->
55-
new FirebaseContextProvider(
56-
c.getProvider(InternalAuthProvider.class),
57-
c.getProvider(FirebaseInstanceIdInternal.class),
58-
c.getDeferred(InternalAppCheckTokenProvider.class),
59-
c.get(liteExecutor)))
60-
.build(),
6148
Component.builder(FunctionsMultiResourceComponent.class)
6249
.name(LIBRARY_NAME)
6350
.add(Dependency.required(Context.class))
64-
.add(Dependency.required(ContextProvider.class))
65-
.add(Dependency.required(FirebaseApp.class))
51+
.add(Dependency.required(FirebaseOptions.class))
52+
.add(Dependency.optionalProvider(InternalAuthProvider.class))
53+
.add(Dependency.requiredProvider(FirebaseInstanceIdInternal.class))
54+
.add(Dependency.deferred(InternalAppCheckTokenProvider.class))
6655
.add(Dependency.required(liteExecutor))
6756
.add(Dependency.required(uiExecutor))
6857
.factory(
6958
c ->
70-
new FunctionsMultiResourceComponent(
71-
c.get(Context.class),
72-
c.get(ContextProvider.class),
73-
c.get(FirebaseApp.class),
74-
c.get(liteExecutor),
75-
c.get(uiExecutor)))
59+
DaggerFunctionsComponent.builder()
60+
.setApplicationContext(c.get(Context.class))
61+
.setFirebaseOptions(c.get(FirebaseOptions.class))
62+
.setLiteExecutor(c.get(liteExecutor))
63+
.setUiExecutor(c.get(uiExecutor))
64+
.setAuth(c.getProvider(InternalAuthProvider.class))
65+
.setIid(c.getProvider(FirebaseInstanceIdInternal.class))
66+
.setAppCheck(c.getDeferred(InternalAppCheckTokenProvider.class))
67+
.build()
68+
.getMultiResourceComponent())
7669
.build(),
7770
LibraryVersionComponent.create(LIBRARY_NAME, BuildConfig.VERSION_NAME));
7871
}

firebase-functions/src/main/java/com/google/firebase/functions/Serializer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class Serializer {
3838

3939
private final DateFormat dateFormat;
4040

41-
public Serializer() {
41+
Serializer() {
4242
// Encode Dates as UTC ISO 8601 strings.
4343
dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
4444
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));

0 commit comments

Comments
 (0)