Skip to content

Commit dd70b46

Browse files
Installations: access FIRHeartbeatInfo from a background thread (#5114)
* FIS: assert heartbeat storage is not accessed in main thread. * FIS: Access hearbeat storage from a background queue.
1 parent 31e054a commit dd70b46

File tree

2 files changed

+63
-44
lines changed

2 files changed

+63
-44
lines changed

FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m

Lines changed: 60 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -92,17 +92,21 @@ - (instancetype)initWithURLSession:(NSURLSession *)URLSession
9292
#pragma mark - Public
9393

9494
- (FBLPromise<FIRInstallationsItem *> *)registerInstallation:(FIRInstallationsItem *)installation {
95-
NSURLRequest *request = [self registerRequestWithInstallation:installation];
96-
return [self sendURLRequest:request].then(
97-
^id _Nullable(FIRInstallationsURLSessionResponse *response) {
95+
return [self registerRequestWithInstallation:installation]
96+
.then(^id _Nullable(NSURLRequest *_Nullable request) {
97+
return [self sendURLRequest:request];
98+
})
99+
.then(^id _Nullable(FIRInstallationsURLSessionResponse *response) {
98100
return [self registeredInstallationWithInstallation:installation serverResponse:response];
99101
});
100102
}
101103

102104
- (FBLPromise<FIRInstallationsItem *> *)refreshAuthTokenForInstallation:
103105
(FIRInstallationsItem *)installation {
104-
NSURLRequest *request = [self authTokenRequestWithInstallation:installation];
105-
return [self sendURLRequest:request]
106+
return [self authTokenRequestWithInstallation:installation]
107+
.then(^id _Nullable(NSURLRequest *_Nullable request) {
108+
return [self sendURLRequest:request];
109+
})
106110
.then(^FBLPromise<FIRInstallationsStoredAuthToken *> *(
107111
FIRInstallationsURLSessionResponse *response) {
108112
return [self authTokenWithServerResponse:response];
@@ -115,17 +119,20 @@ - (instancetype)initWithURLSession:(NSURLSession *)URLSession
115119
}
116120

117121
- (FBLPromise<FIRInstallationsItem *> *)deleteInstallation:(FIRInstallationsItem *)installation {
118-
NSURLRequest *request = [self deleteInstallationRequestWithInstallation:installation];
119-
return [[self sendURLRequest:request]
120-
then:^id _Nullable(FIRInstallationsURLSessionResponse *_Nullable value) {
122+
return [self deleteInstallationRequestWithInstallation:installation]
123+
.then(^id _Nullable(NSURLRequest *_Nullable request) {
124+
return [self sendURLRequest:request];
125+
})
126+
.then(^id _Nullable(FIRInstallationsURLSessionResponse *_Nullable value) {
121127
// Return the original installation on success.
122128
return installation;
123-
}];
129+
});
124130
}
125131

126132
#pragma mark - Register Installation
127133

128-
- (NSURLRequest *)registerRequestWithInstallation:(FIRInstallationsItem *)installation {
134+
- (FBLPromise<NSURLRequest *> *)registerRequestWithInstallation:
135+
(FIRInstallationsItem *)installation {
129136
NSString *URLString = [NSString stringWithFormat:@"%@/v1/projects/%@/installations/",
130137
kFIRInstallationsAPIBaseURL, self.projectID];
131138
NSURL *URL = [NSURL URLWithString:URLString];
@@ -176,7 +183,8 @@ - (NSURLRequest *)registerRequestWithInstallation:(FIRInstallationsItem *)instal
176183

177184
#pragma mark - Auth token
178185

179-
- (NSURLRequest *)authTokenRequestWithInstallation:(FIRInstallationsItem *)installation {
186+
- (FBLPromise<NSURLRequest *> *)authTokenRequestWithInstallation:
187+
(FIRInstallationsItem *)installation {
180188
NSString *URLString =
181189
[NSString stringWithFormat:@"%@/v1/projects/%@/installations/%@/authTokens:generate",
182190
kFIRInstallationsAPIBaseURL, self.projectID,
@@ -216,7 +224,8 @@ - (NSURLRequest *)authTokenRequestWithInstallation:(FIRInstallationsItem *)insta
216224

217225
#pragma mark - Delete Installation
218226

219-
- (NSURLRequest *)deleteInstallationRequestWithInstallation:(FIRInstallationsItem *)installation {
227+
- (FBLPromise<NSURLRequest *> *)deleteInstallationRequestWithInstallation:
228+
(FIRInstallationsItem *)installation {
220229
NSString *URLString = [NSString stringWithFormat:@"%@/v1/projects/%@/installations/%@/",
221230
kFIRInstallationsAPIBaseURL, self.projectID,
222231
installation.firebaseInstallationID];
@@ -229,45 +238,52 @@ - (NSURLRequest *)deleteInstallationRequestWithInstallation:(FIRInstallationsIte
229238
}
230239

231240
#pragma mark - URL Request
232-
- (NSURLRequest *)requestWithURL:(NSURL *)requestURL
233-
HTTPMethod:(NSString *)HTTPMethod
234-
bodyDict:(NSDictionary *)bodyDict
235-
refreshToken:(nullable NSString *)refreshToken {
241+
- (FBLPromise<NSURLRequest *> *)requestWithURL:(NSURL *)requestURL
242+
HTTPMethod:(NSString *)HTTPMethod
243+
bodyDict:(NSDictionary *)bodyDict
244+
refreshToken:(nullable NSString *)refreshToken {
236245
return [self requestWithURL:requestURL
237246
HTTPMethod:HTTPMethod
238247
bodyDict:bodyDict
239248
refreshToken:refreshToken
240249
additionalHeaders:nil];
241250
}
242251

243-
- (NSURLRequest *)requestWithURL:(NSURL *)requestURL
244-
HTTPMethod:(NSString *)HTTPMethod
245-
bodyDict:(NSDictionary *)bodyDict
246-
refreshToken:(nullable NSString *)refreshToken
247-
additionalHeaders:
248-
(nullable NSDictionary<NSString *, NSString *> *)additionalHeaders {
249-
__block NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestURL];
250-
request.HTTPMethod = HTTPMethod;
251-
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
252-
[request addValue:self.APIKey forHTTPHeaderField:kFIRInstallationsAPIKey];
253-
[request addValue:bundleIdentifier forHTTPHeaderField:kFIRInstallationsBundleId];
254-
[self setJSONHTTPBody:bodyDict forRequest:request];
255-
if (refreshToken) {
256-
NSString *authHeader = [NSString stringWithFormat:@"FIS_v2 %@", refreshToken];
257-
[request setValue:authHeader forHTTPHeaderField:@"Authorization"];
258-
}
259-
// User agent Header.
260-
[request setValue:[FIRApp firebaseUserAgent] forHTTPHeaderField:kFIRInstallationsUserAgentKey];
261-
// Heartbeat Header.
262-
[request setValue:@([FIRHeartbeatInfo heartbeatCodeForTag:kFIRInstallationsHeartbeatTag])
263-
.stringValue
264-
forHTTPHeaderField:kFIRInstallationsHeartbeatKey];
265-
[additionalHeaders enumerateKeysAndObjectsUsingBlock:^(
266-
NSString *_Nonnull key, NSString *_Nonnull obj, BOOL *_Nonnull stop) {
267-
[request setValue:obj forHTTPHeaderField:key];
268-
}];
269-
270-
return [request copy];
252+
- (FBLPromise<NSURLRequest *> *)requestWithURL:(NSURL *)requestURL
253+
HTTPMethod:(NSString *)HTTPMethod
254+
bodyDict:(NSDictionary *)bodyDict
255+
refreshToken:(nullable NSString *)refreshToken
256+
additionalHeaders:(nullable NSDictionary<NSString *, NSString *> *)
257+
additionalHeaders {
258+
return [FBLPromise
259+
onQueue:dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)
260+
do:^id _Nullable {
261+
__block NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestURL];
262+
request.HTTPMethod = HTTPMethod;
263+
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
264+
[request addValue:self.APIKey forHTTPHeaderField:kFIRInstallationsAPIKey];
265+
[request addValue:bundleIdentifier forHTTPHeaderField:kFIRInstallationsBundleId];
266+
[self setJSONHTTPBody:bodyDict forRequest:request];
267+
if (refreshToken) {
268+
NSString *authHeader = [NSString stringWithFormat:@"FIS_v2 %@", refreshToken];
269+
[request setValue:authHeader forHTTPHeaderField:@"Authorization"];
270+
}
271+
// User agent Header.
272+
[request setValue:[FIRApp firebaseUserAgent]
273+
forHTTPHeaderField:kFIRInstallationsUserAgentKey];
274+
// Heartbeat Header.
275+
[request setValue:@([FIRHeartbeatInfo
276+
heartbeatCodeForTag:kFIRInstallationsHeartbeatTag])
277+
.stringValue
278+
forHTTPHeaderField:kFIRInstallationsHeartbeatKey];
279+
[additionalHeaders
280+
enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull key, NSString *_Nonnull obj,
281+
BOOL *_Nonnull stop) {
282+
[request setValue:obj forHTTPHeaderField:key];
283+
}];
284+
285+
return [request copy];
286+
}];
271287
}
272288

273289
- (FBLPromise<FIRInstallationsURLSessionResponse *> *)URLRequestPromise:(NSURLRequest *)request {

FirebaseInstallations/Source/Tests/Unit/FIRInstallationsAPIServiceTests.m

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ - (void)setUp {
5656
projectID:self.projectID];
5757
self.heartbeatMock = OCMClassMock([FIRHeartbeatInfo class]);
5858
OCMStub([self.heartbeatMock heartbeatCodeForTag:@"fire-installations"])
59+
.andDo(^(NSInvocation *invocation) {
60+
XCTAssertFalse([NSThread isMainThread]);
61+
})
5962
.andReturn(FIRHeartbeatInfoCodeCombined);
6063
}
6164

0 commit comments

Comments
 (0)