Skip to content

Commit 4172c44

Browse files
authored
Merge branch 'master' into rl.json.relnotes
2 parents 96792ab + 7ee2c64 commit 4172c44

File tree

8 files changed

+140
-9
lines changed

8 files changed

+140
-9
lines changed

firebase-common/src/main/java/com/google/firebase/FirebaseApp.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ public static FirebaseApp getInstance() {
180180
+ ". Make sure to call "
181181
+ "FirebaseApp.initializeApp(Context) first.");
182182
}
183+
defaultApp.defaultHeartBeatController.get().registerHeartBeat();
183184
return defaultApp;
184185
}
185186
}

firebase-common/src/main/java/com/google/firebase/heartbeatinfo/HeartBeatInfoStorage.java

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,22 +75,43 @@ int getHeartBeatCount() {
7575

7676
synchronized void deleteAllHeartBeats() {
7777
SharedPreferences.Editor editor = firebaseSharedPreferences.edit();
78+
int counter = 0;
7879
for (Map.Entry<String, ?> entry : this.firebaseSharedPreferences.getAll().entrySet()) {
7980
if (entry.getValue() instanceof Set) {
80-
editor.remove(entry.getKey());
81+
// All other heartbeats other than the heartbeats stored today will be deleted.
82+
Set<String> dates = (Set<String>) entry.getValue();
83+
String today = getFormattedDate(System.currentTimeMillis());
84+
String key = entry.getKey();
85+
if (dates.contains(today)) {
86+
Set<String> userAgentDateSet = new HashSet<>();
87+
userAgentDateSet.add(today);
88+
counter += 1;
89+
editor.putStringSet(key, userAgentDateSet);
90+
} else {
91+
editor.remove(key);
92+
}
8193
}
8294
}
83-
editor.remove(HEART_BEAT_COUNT_TAG);
95+
if (counter == 0) {
96+
editor.remove(HEART_BEAT_COUNT_TAG);
97+
} else {
98+
editor.putLong(HEART_BEAT_COUNT_TAG, counter);
99+
}
100+
84101
editor.commit();
85102
}
86103

87104
synchronized List<HeartBeatResult> getAllHeartBeats() {
88105
ArrayList<HeartBeatResult> heartBeatResults = new ArrayList<>();
89106
for (Map.Entry<String, ?> entry : this.firebaseSharedPreferences.getAll().entrySet()) {
90107
if (entry.getValue() instanceof Set) {
91-
heartBeatResults.add(
92-
HeartBeatResult.create(
93-
entry.getKey(), new ArrayList<String>((Set<String>) entry.getValue())));
108+
Set<String> dates = new HashSet<>((Set<String>) entry.getValue());
109+
String today = getFormattedDate(System.currentTimeMillis());
110+
dates.remove(today);
111+
if (!dates.isEmpty()) {
112+
heartBeatResults.add(
113+
HeartBeatResult.create(entry.getKey(), new ArrayList<String>(dates)));
114+
}
94115
}
95116
}
96117
updateGlobalHeartBeat(System.currentTimeMillis());

firebase-common/src/test/java/com/google/firebase/heartbeatinfo/HeartBeatInfoStorageTest.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import androidx.test.runner.AndroidJUnit4;
2323
import java.util.ArrayList;
2424
import java.util.Collections;
25+
import java.util.HashSet;
2526
import org.junit.After;
2627
import org.junit.Before;
2728
import org.junit.Test;
@@ -179,14 +180,30 @@ public void shouldSendGlobalHeartBeat_answerIsNo() {
179180
assertThat(heartBeatInfoStorage.shouldSendGlobalHeartBeat(1)).isFalse();
180181
}
181182

183+
@Test
184+
public void currentDayHeartbeatNotSent_updatesCorrectly() {
185+
long millis = System.currentTimeMillis();
186+
assertThat(heartBeatInfoStorage.getHeartBeatCount()).isEqualTo(0);
187+
heartBeatInfoStorage.storeHeartBeat(millis, "test-agent");
188+
assertThat(heartBeatInfoStorage.getHeartBeatCount()).isEqualTo(1);
189+
assertThat(heartBeatInfoStorage.getAllHeartBeats().size()).isEqualTo(0);
190+
heartBeatInfoStorage.deleteAllHeartBeats();
191+
assertThat(heartBeatInfoStorage.getHeartBeatCount()).isEqualTo(1);
192+
assertThat(heartBeatSharedPreferences.getStringSet("test-agent", new HashSet<>())).isNotEmpty();
193+
heartBeatInfoStorage.storeHeartBeat(millis, "test-agent-1");
194+
assertThat(heartBeatSharedPreferences.getStringSet("test-agent", new HashSet<>())).isEmpty();
195+
assertThat(heartBeatSharedPreferences.getStringSet("test-agent-1", new HashSet<>()))
196+
.isNotEmpty();
197+
}
198+
182199
@Test
183200
public void postHeartBeatCleanUp_worksCorrectly() {
184201
long millis = System.currentTimeMillis();
185202
// Store using new method
186203
heartBeatInfoStorage.storeHeartBeat(millis, "test-agent");
187204
// Get global heartbeat using old method
188205
assertThat(heartBeatInfoStorage.shouldSendGlobalHeartBeat(millis)).isTrue();
189-
assertThat(heartBeatInfoStorage.getAllHeartBeats().size()).isEqualTo(1);
206+
assertThat(heartBeatInfoStorage.getAllHeartBeats().size()).isEqualTo(0);
190207
heartBeatInfoStorage.postHeartBeatCleanUp();
191208
assertThat(heartBeatInfoStorage.getAllHeartBeats().size()).isEqualTo(0);
192209
// Try storing using new method again.

firebase-functions/ktx/api.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ package com.google.firebase.functions.ktx {
66
method @NonNull public static com.google.firebase.functions.FirebaseFunctions functions(@NonNull com.google.firebase.ktx.Firebase, @NonNull com.google.firebase.FirebaseApp app);
77
method @NonNull public static com.google.firebase.functions.FirebaseFunctions functions(@NonNull com.google.firebase.ktx.Firebase, @NonNull com.google.firebase.FirebaseApp app, @NonNull String regionOrCustomDomain);
88
method @NonNull public static com.google.firebase.functions.FirebaseFunctions getFunctions(@NonNull com.google.firebase.ktx.Firebase);
9+
method @NonNull public static com.google.firebase.functions.HttpsCallableReference getHttpsCallable(@NonNull com.google.firebase.functions.FirebaseFunctions, @NonNull String name, @NonNull kotlin.jvm.functions.Function1<? super com.google.firebase.functions.HttpsCallableOptions.Builder,kotlin.Unit> init);
10+
method @NonNull public static com.google.firebase.functions.HttpsCallableReference getHttpsCallableFromUrl(@NonNull com.google.firebase.functions.FirebaseFunctions, @NonNull java.net.URL url, @NonNull kotlin.jvm.functions.Function1<? super com.google.firebase.functions.HttpsCallableOptions.Builder,kotlin.Unit> init);
911
}
1012

1113
}

firebase-functions/ktx/src/main/kotlin/com/google/firebase/functions/ktx/Functions.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@ import com.google.firebase.FirebaseApp
1919
import com.google.firebase.components.Component
2020
import com.google.firebase.components.ComponentRegistrar
2121
import com.google.firebase.functions.FirebaseFunctions
22+
import com.google.firebase.functions.HttpsCallableOptions
23+
import com.google.firebase.functions.HttpsCallableReference
2224
import com.google.firebase.ktx.Firebase
2325
import com.google.firebase.platforminfo.LibraryVersionComponent
26+
import java.net.URL
2427

2528
/** Returns the [FirebaseFunctions] instance of the default [FirebaseApp]. */
2629
val Firebase.functions: FirebaseFunctions
@@ -45,3 +48,23 @@ class FirebaseFunctionsKtxRegistrar : ComponentRegistrar {
4548
override fun getComponents(): List<Component<*>> =
4649
listOf(LibraryVersionComponent.create(LIBRARY_NAME, BuildConfig.VERSION_NAME))
4750
}
51+
52+
/** Returns a reference to the Callable HTTPS trigger with the given name and call options. */
53+
fun FirebaseFunctions.getHttpsCallable(
54+
name: String,
55+
init: HttpsCallableOptions.Builder.() -> Unit
56+
): HttpsCallableReference {
57+
val builder = HttpsCallableOptions.Builder()
58+
builder.init()
59+
return getHttpsCallable(name, builder.build())
60+
}
61+
62+
/** Returns a reference to the Callable HTTPS trigger with the given URL and call options. */
63+
fun FirebaseFunctions.getHttpsCallableFromUrl(
64+
url: URL,
65+
init: HttpsCallableOptions.Builder.() -> Unit
66+
): HttpsCallableReference {
67+
val builder = HttpsCallableOptions.Builder()
68+
builder.init()
69+
return getHttpsCallableFromUrl(url, builder.build())
70+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2023 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+
/**
18+
* Returns true if the {@link HttpsCallableReference} is configured to use FAC limited-use tokens.
19+
*/
20+
fun HttpsCallableReference.usesLimitedUseFacTokens() = options.getLimitedUseAppCheckTokens()

firebase-functions/ktx/src/test/kotlin/com/google/firebase/functions/ktx/FunctionsTests.kt

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ import com.google.common.truth.Truth.assertThat
1919
import com.google.firebase.FirebaseApp
2020
import com.google.firebase.FirebaseOptions
2121
import com.google.firebase.functions.FirebaseFunctions
22+
import com.google.firebase.functions.usesLimitedUseFacTokens
2223
import com.google.firebase.ktx.Firebase
2324
import com.google.firebase.ktx.app
2425
import com.google.firebase.ktx.initialize
2526
import com.google.firebase.platforminfo.UserAgentPublisher
27+
import java.net.URL
2628
import org.junit.After
2729
import org.junit.Before
2830
import org.junit.Test
@@ -100,3 +102,50 @@ class LibraryVersionTest : BaseTestCase() {
100102
assertThat(publisher.userAgent).contains(LIBRARY_NAME)
101103
}
102104
}
105+
106+
@RunWith(RobolectricTestRunner::class)
107+
class AppCheckLimitedUseTest : BaseTestCase() {
108+
@Test
109+
fun `FirebaseFunctions#getHttpsCallable should not use limited-use tokens by default`() {
110+
val callable = Firebase.functions.getHttpsCallable("function")
111+
assertThat(callable.usesLimitedUseFacTokens()).isFalse()
112+
}
113+
114+
@Test
115+
fun `FirebaseFunctions#getHttpsCallable should build callable with FAC settings (when true)`() {
116+
val callable =
117+
Firebase.functions.getHttpsCallable("function") { limitedUseAppCheckTokens = true }
118+
assertThat(callable.usesLimitedUseFacTokens()).isTrue()
119+
}
120+
121+
@Test
122+
fun `FirebaseFunctions#getHttpsCallable should build callable with FAC settings (when false)`() {
123+
val callable =
124+
Firebase.functions.getHttpsCallable("function") { limitedUseAppCheckTokens = false }
125+
assertThat(callable.usesLimitedUseFacTokens()).isFalse()
126+
}
127+
128+
@Test
129+
fun `FirebaseFunctions#getHttpsCallableFromUrl should not use limited-use tokens by default`() {
130+
val callable = Firebase.functions.getHttpsCallableFromUrl(URL("https://functions.test"))
131+
assertThat(callable.usesLimitedUseFacTokens()).isFalse()
132+
}
133+
134+
@Test
135+
fun `FirebaseFunctions#getHttpsCallableFromUrl callable with FAC settings (when true)`() {
136+
val callable =
137+
Firebase.functions.getHttpsCallableFromUrl(URL("https://functions.test")) {
138+
limitedUseAppCheckTokens = true
139+
}
140+
assertThat(callable.usesLimitedUseFacTokens()).isTrue()
141+
}
142+
143+
@Test
144+
fun `FirebaseFunctions#getHttpsCallableFromUrl callable with FAC settings (when false)`() {
145+
val callable =
146+
Firebase.functions.getHttpsCallableFromUrl(URL("https://functions.test")) {
147+
limitedUseAppCheckTokens = false
148+
}
149+
assertThat(callable.usesLimitedUseFacTokens()).isFalse()
150+
}
151+
}

transport/transport-runtime/transport-runtime.gradle

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,7 @@ firebaseLibrary {
5454
testLab {
5555
enabled = true
5656

57-
// TODO(yifany): Blueline-28 was added in #4558, but has never passed.
58-
// Disabling for now. Re-enable later if needed.
59-
// device 'model=blueline,version=28' // Pixel3
57+
device 'model=blueline,version=28' // Pixel3
6058
device 'model=walleye,version=27' // Pixel2
6159
device 'model=Nexus4,version=22'
6260
device 'model=Nexus7,version=21'

0 commit comments

Comments
 (0)