Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions FirebaseAuth/Sources/Swift/Backend/AuthBackend.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ class AuthBackend {
class func request(withURL url: URL,
contentType: String,
requestConfiguration: AuthRequestConfiguration) async -> URLRequest {
// Kick off tasks for the async header values.
async let heartbeatsHeaderValue = requestConfiguration.heartbeatLogger?.asyncHeaderValue!()
async let appCheckTokenHeaderValue = requestConfiguration.appCheck?
.getToken(forcingRefresh: true)

var request = URLRequest(url: url)
request.setValue(contentType, forHTTPHeaderField: "Content-Type")
let additionalFrameworkMarker = requestConfiguration
Expand All @@ -106,13 +111,6 @@ class AuthBackend {
request.setValue(clientVersion, forHTTPHeaderField: "X-Client-Version")
request.setValue(Bundle.main.bundleIdentifier, forHTTPHeaderField: "X-Ios-Bundle-Identifier")
request.setValue(requestConfiguration.appID, forHTTPHeaderField: "X-Firebase-GMPID")
if let heartbeatLogger = requestConfiguration.heartbeatLogger {
// The below call synchronously dispatches to a queue. To avoid blocking
// the shared concurrency queue, `async let` will spawn the process on
// a separate thread.
async let heartbeatsHeaderValue = heartbeatLogger.headerValue()
await request.setValue(heartbeatsHeaderValue, forHTTPHeaderField: "X-Firebase-Client")
}
request.httpMethod = requestConfiguration.httpMethod
let preferredLocalizations = Bundle.main.preferredLocalizations
if preferredLocalizations.count > 0 {
Expand All @@ -122,8 +120,9 @@ class AuthBackend {
languageCode.count > 0 {
request.setValue(languageCode, forHTTPHeaderField: "X-Firebase-Locale")
}
if let appCheck = requestConfiguration.appCheck {
let tokenResult = await appCheck.getToken(forcingRefresh: false)
// Wait for the async header values.
await request.setValue(heartbeatsHeaderValue, forHTTPHeaderField: "X-Firebase-Client")
await appCheckTokenHeaderValue.map { tokenResult in
if let error = tokenResult.error {
AuthLog.logWarning(code: "I-AUT000018",
message: "Error getting App Check token; using placeholder " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,10 @@ class AuthBackendRPCImplementationTests: RPCBaseTests {

#if COCOAPODS || SWIFT_PACKAGE
private class FakeHeartbeatLogger: NSObject, FIRHeartbeatLoggerProtocol {
func asyncHeaderValue() async -> String? {
headerValue()
}

func headerValue() -> String? {
let payload = flushHeartbeatsIntoPayload()
guard !payload.isEmpty else {
Expand Down
13 changes: 9 additions & 4 deletions FirebaseCore/Extension/FIRHeartbeatLogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,18 @@ typedef NS_ENUM(NSInteger, FIRDailyHeartbeatCode) {
/// Asynchronously logs a heartbeat.
- (void)log;

/// Gets the heartbeat code for today.
- (FIRDailyHeartbeatCode)heartbeatCodeForToday;

#ifndef FIREBASE_BUILD_CMAKE
/// Return the headerValue for the HeartbeatLogger.
/// Return the header value for the heartbeat logger.
- (NSString *_Nullable)headerValue;
#endif // FIREBASE_BUILD_CMAKE

/// Gets the heartbeat code for today.
- (FIRDailyHeartbeatCode)heartbeatCodeForToday;
@optional
/// Returns the header value for the heartbeat logger via the given completion handler..
- (void)asyncHeaderValueWithCompletionHandler:(void (^)(NSString *_Nullable))completionHandler
API_AVAILABLE(ios(13.0), macosx(10.15), macCatalyst(13.0), tvos(13.0), watchos(6.0));
#endif // FIREBASE_BUILD_CMAKE

@end

Expand Down
7 changes: 7 additions & 0 deletions FirebaseCore/Sources/FIRHeartbeatLogger.m
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ - (NSString *_Nullable)headerValue {
return FIRHeaderValueFromHeartbeatsPayload([self flushHeartbeatsIntoPayload]);
}

- (void)asyncHeaderValueWithCompletionHandler:(void (^)(NSString *_Nullable))completionHandler
API_AVAILABLE(ios(13.0), macosx(10.15), macCatalyst(13.0), tvos(13.0), watchos(6.0)) {
[self flushHeartbeatsIntoPayloadWithCompletionHandler:^(FIRHeartbeatsPayload *payload) {
completionHandler(FIRHeaderValueFromHeartbeatsPayload(payload));
}];
}

- (FIRHeartbeatsPayload *)flushHeartbeatsIntoPayload {
FIRHeartbeatsPayload *payload = [_heartbeatController flush];
return payload;
Expand Down
Loading