Skip to content

Commit d4b6e1c

Browse files
committed
Merge branch 'master' into firebase-sessions
2 parents 51175b5 + fa7a068 commit d4b6e1c

File tree

13 files changed

+172
-35
lines changed

13 files changed

+172
-35
lines changed

appcheck/firebase-appcheck/src/main/java/com/google/firebase/appcheck/FirebaseAppCheck.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ public abstract void installAppCheckProviderFactory(
7676
* requests to a non-Firebase backend. Requests to Firebase backends are authorized automatically
7777
* if configured.
7878
*
79-
* <p>If your non-Firebase backend exposes sensitive or expensive endpoints that has low traffic
79+
* <p>If your non-Firebase backend exposes a sensitive or expensive endpoint that has low traffic
8080
* volume, consider protecting it with <a
8181
* href=https://firebase.google.com/docs/app-check/custom-resource-backend#replay-protection>Replay
82-
* Protection</a>. In this case, use the #getLimitedUseAppCheckToken() instead to obtain a
82+
* Protection</a>. In this case, use {@link #getLimitedUseAppCheckToken()} instead to obtain a
8383
* limited-use token.
8484
*/
8585
@NonNull
@@ -92,8 +92,8 @@ public abstract void installAppCheckProviderFactory(
9292
* <p>Returns limited-use tokens that are intended for use with your non-Firebase backend
9393
* endpoints that are protected with <a
9494
* href=https://firebase.google.com/docs/app-check/custom-resource-backend#replay-protection>Replay
95-
* Protection</a>. This method does not affect the token generation behavior of the
96-
* #getAppCheckToken() method.
95+
* Protection</a>. This method does not affect the token generation behavior of the {@link
96+
* #getAppCheckToken(boolean forceRefresh)} method.
9797
*/
9898
@NonNull
9999
public abstract Task<AppCheckToken> getLimitedUseAppCheckToken();

docs/make_release_notes.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import argparse
2020
import configparser
21+
import json
2122
import re
2223
import os
2324
import string
@@ -219,15 +220,15 @@ def _get_version(self):
219220

220221

221222
def read_release_cfg(release_cfg_path):
222-
config = configparser.ConfigParser(allow_no_value=True, delimiters=('=',))
223-
config.read(release_cfg_path)
223+
with open(release_cfg_path) as fd:
224+
config = json.load(fd)
224225
return config
225226

226227

227228
def main():
228229
parser = argparse.ArgumentParser(description='Create release notes.')
229230
parser.add_argument('--releasecfg',
230-
default='release.cfg',
231+
default='release.json',
231232
required=False,
232233
help='Path to the release.cfg file to use')
233234
parser.add_argument('--products',
@@ -246,12 +247,12 @@ def main():
246247
if args.products:
247248
products = args.products.split(',')
248249
else:
249-
products = list(release_cfg['modules'])
250+
products = list(release_cfg['libraries'])
250251

251252
if args.generated_name:
252253
generated_name = args.generated_name
253254
else:
254-
generated_name = release_cfg['release']['name'].lower().strip()
255+
generated_name = release_cfg['name'].lower().strip()
255256

256257
for product in products:
257258
if product.startswith(':'):

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+
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,26 +202,26 @@ public static FirebaseFunctions getInstance() {
202202
return getInstance(FirebaseApp.getInstance(), "us-central1");
203203
}
204204

205-
/** Returns a reference to the Callable HTTPS trigger with the given name. */
205+
/** Returns a reference to the callable HTTPS trigger with the given name. */
206206
@NonNull
207207
public HttpsCallableReference getHttpsCallable(@NonNull String name) {
208208
return new HttpsCallableReference(this, name, new HttpsCallOptions());
209209
}
210210

211-
/** Returns a reference to the Callable HTTPS trigger with the provided url. */
211+
/** Returns a reference to the callable HTTPS trigger with the provided URL. */
212212
@NonNull
213213
public HttpsCallableReference getHttpsCallableFromUrl(@NonNull URL url) {
214214
return new HttpsCallableReference(this, url, new HttpsCallOptions());
215215
}
216216

217-
/** Returns a reference to the Callable HTTPS trigger with the given name and call options. */
217+
/** Returns a reference to the callable HTTPS trigger with the given name and call options. */
218218
@NonNull
219219
public HttpsCallableReference getHttpsCallable(
220220
@NonNull String name, @NonNull HttpsCallableOptions options) {
221221
return new HttpsCallableReference(this, name, new HttpsCallOptions(options));
222222
}
223223

224-
/** Returns a reference to the Callable HTTPS trigger with the provided url and call options. */
224+
/** Returns a reference to the callable HTTPS trigger with the provided URL and call options. */
225225
@NonNull
226226
public HttpsCallableReference getHttpsCallableFromUrl(
227227
@NonNull URL url, @NonNull HttpsCallableOptions options) {

firebase-perf/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Unreleased
22

3+
* [fixed] Fixed app start trace creation where some measured time could be NULL (#4730).
4+
35

46
# 20.3.2
57
* [changed] Updated JavaLite, protoc, protobuf-java-util to 3.21.11.

firebase-perf/src/main/java/com/google/firebase/perf/metrics/AppStartTrace.java

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -411,19 +411,22 @@ private void logAppStartTrace() {
411411
.setDurationUs(getClassLoadTimeCompat().getDurationMicros(onCreateTime));
412412
subtraces.add(traceMetricBuilder.build());
413413

414-
traceMetricBuilder = TraceMetric.newBuilder();
415-
traceMetricBuilder
416-
.setName(Constants.TraceNames.ON_START_TRACE_NAME.toString())
417-
.setClientStartTimeUs(onCreateTime.getMicros())
418-
.setDurationUs(onCreateTime.getDurationMicros(onStartTime));
419-
subtraces.add(traceMetricBuilder.build());
420-
421-
traceMetricBuilder = TraceMetric.newBuilder();
422-
traceMetricBuilder
423-
.setName(Constants.TraceNames.ON_RESUME_TRACE_NAME.toString())
424-
.setClientStartTimeUs(onStartTime.getMicros())
425-
.setDurationUs(onStartTime.getDurationMicros(onResumeTime));
426-
subtraces.add(traceMetricBuilder.build());
414+
// OnStartTime is not captured in all situations, so checking for valid value before using it.
415+
if (onStartTime != null) {
416+
traceMetricBuilder = TraceMetric.newBuilder();
417+
traceMetricBuilder
418+
.setName(Constants.TraceNames.ON_START_TRACE_NAME.toString())
419+
.setClientStartTimeUs(onCreateTime.getMicros())
420+
.setDurationUs(onCreateTime.getDurationMicros(onStartTime));
421+
subtraces.add(traceMetricBuilder.build());
422+
423+
traceMetricBuilder = TraceMetric.newBuilder();
424+
traceMetricBuilder
425+
.setName(Constants.TraceNames.ON_RESUME_TRACE_NAME.toString())
426+
.setClientStartTimeUs(onStartTime.getMicros())
427+
.setDurationUs(onStartTime.getDurationMicros(onResumeTime));
428+
subtraces.add(traceMetricBuilder.build());
429+
}
427430

428431
metric.addAllSubtraces(subtraces).addPerfSessions(this.startSession.build());
429432

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)