Skip to content

Commit 72397a0

Browse files
authored
Use FIRInstallations SDK to fetch FID and FIS token, send those values in requests to FIAM backend (#5081)
* Depend on FIRInstallations instead of IID, load an installations object into FIRInAppMessagingPrivate.h * Bootstrap FIRInAppMessaging.h with an instance of FIRInstallations * Update FIRIAMClientInfoFetcher to use FIRInstallations method to grab FID and FIS Token * Call new client info fetcher method * Fix up tests * Change nullability for FIRInstallations object, handle null case * More verbose comments in FIRIAMClientInfoFetcher, call completion in case that FIS token is fetched, but FID fails * Throw error and call completion if Firebase Installations object is not created * Send FIS token with method fetch requests * Add test class for FIRIAMClientInfoFetcher * Refactor FIRIAMClientInfoFetcher to get a FIRInstallations object injected * Add unit testing for fetchFirebaseInstallationDataWithProjectNumber: in FIRIAMClientInfoFetcher * Streamline unit tests, add case for nil FirebaseInstallations, clean up comments that were left in
1 parent 27fd02a commit 72397a0

13 files changed

+345
-138
lines changed

FirebaseInAppMessaging.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ See more product details at https://firebase.google.com/products/in-app-messagin
4343

4444
s.dependency 'FirebaseCore', '~> 6.2'
4545
s.ios.dependency 'FirebaseAnalyticsInterop', '~> 1.3'
46-
s.dependency 'FirebaseInstanceID', '~> 4.0'
46+
s.dependency 'FirebaseInstallations', '~> 1.1'
4747
s.dependency 'GoogleDataTransportCCTSupport', '~> 2.0'
4848
s.dependency 'FirebaseABTesting', '~> 3.2'
4949

FirebaseInAppMessaging/Sources/Analytics/FIRIAMClearcutLogger.m

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ @interface FIRIAMClearcutLogger ()
3737
@end
3838

3939
@implementation FIRIAMClearcutLogger {
40-
NSString *_iid;
40+
// Firebase installations ID.
41+
NSString *_FID;
4142
}
4243
- (instancetype)initWithFBProjectNumber:(NSString *)fbProjectNumber
4344
fbAppId:(NSString *)fbAppId
@@ -105,13 +106,13 @@ - (NSString *)constructSourceExtensionJsonForClearcutWithEventType:
105106
(FIRIAMAnalyticsLogEventType)eventType
106107
forCampaignID:(NSString *)campaignID
107108
eventTimeInMs:(NSNumber *)eventTimeInMs
108-
instanceID:(NSString *)instanceID {
109+
installationID:(NSString *)installationID {
109110
NSMutableDictionary *campaignAnalyticsDict = [[NSMutableDictionary alloc] init];
110111

111112
campaignAnalyticsDict[@"project_number"] = self.fbProjectNumber;
112113
campaignAnalyticsDict[@"campaign_id"] = campaignID;
113114
campaignAnalyticsDict[@"client_app"] =
114-
@{@"google_app_id" : self.fbAppId, @"firebase_instance_id" : instanceID};
115+
@{@"google_app_id" : self.fbAppId, @"firebase_instance_id" : installationID};
115116
campaignAnalyticsDict[@"client_timestamp_millis"] = eventTimeInMs;
116117
[self.class updateSourceExtensionDictWithAnalyticsEventEnumType:eventType
117118
forDict:campaignAnalyticsDict];
@@ -142,14 +143,14 @@ - (NSString *)constructSourceExtensionJsonForClearcutWithEventType:
142143
- (void)logAnalyticsEventForType:(FIRIAMAnalyticsLogEventType)eventType
143144
forCampaignID:(NSString *)campaignID
144145
withEventTimeInMs:(nullable NSNumber *)eventTimeInMs
145-
IID:(NSString *)iid
146+
FID:(NSString *)FID
146147
completion:(void (^)(BOOL success))completion {
147148
NSTimeInterval nowInMs = [self.timeFetcher currentTimestampInSeconds] * 1000;
148149
if (eventTimeInMs == nil) {
149150
eventTimeInMs = @((long)nowInMs);
150151
}
151152

152-
if (!iid) {
153+
if (!FID) {
153154
FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM210009",
154155
@"Instance ID is nil, event %ld for campaign ID %@ will not be sent",
155156
(long)eventType, campaignID);
@@ -160,7 +161,7 @@ - (void)logAnalyticsEventForType:(FIRIAMAnalyticsLogEventType)eventType
160161
[self constructSourceExtensionJsonForClearcutWithEventType:eventType
161162
forCampaignID:campaignID
162163
eventTimeInMs:eventTimeInMs
163-
instanceID:iid];
164+
installationID:FID];
164165

165166
FIRIAMClearcutLogRecord *newRecord = [[FIRIAMClearcutLogRecord alloc]
166167
initWithExtensionJsonString:sourceExtensionJsonString
@@ -177,33 +178,35 @@ - (void)logAnalyticsEventForType:(FIRIAMAnalyticsLogEventType)eventType
177178
withCampaignName:(NSString *)campaignName
178179
eventTimeInMs:(nullable NSNumber *)eventTimeInMs
179180
completion:(void (^)(BOOL success))completion {
180-
if (!_iid) {
181+
if (!_FID) {
181182
[self.clientInfoFetcher
182-
fetchFirebaseIIDDataWithProjectNumber:self.fbProjectNumber
183-
withCompletion:^(NSString *_Nullable iid, NSString *_Nullable token,
184-
NSError *_Nullable error) {
185-
if (error) {
186-
FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM210001",
187-
@"Failed to get iid value for clearcut logging %@",
188-
error);
189-
completion(NO);
190-
} else {
191-
// persist iid through the whole life-cycle
192-
self->_iid = iid;
193-
[self logAnalyticsEventForType:eventType
194-
forCampaignID:campaignID
195-
withEventTimeInMs:eventTimeInMs
196-
IID:iid
197-
completion:completion];
198-
}
199-
}];
183+
fetchFirebaseInstallationDataWithProjectNumber:self.fbProjectNumber
184+
withCompletion:^(NSString *_Nullable FID,
185+
NSString *_Nullable FISToken,
186+
NSError *_Nullable error) {
187+
if (error) {
188+
FIRLogWarning(
189+
kFIRLoggerInAppMessaging, @"I-IAM210001",
190+
@"Failed to get iid value for clearcut logging %@",
191+
error);
192+
completion(NO);
193+
} else {
194+
// persist FID through the whole life-cycle
195+
self->_FID = FID;
196+
[self logAnalyticsEventForType:eventType
197+
forCampaignID:campaignID
198+
withEventTimeInMs:eventTimeInMs
199+
FID:FID
200+
completion:completion];
201+
}
202+
}];
200203
} else {
201204
FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM210004",
202205
@"Using remembered iid for event logging");
203206
[self logAnalyticsEventForType:eventType
204207
forCampaignID:campaignID
205208
withEventTimeInMs:eventTimeInMs
206-
IID:_iid
209+
FID:_FID
207210
completion:completion];
208211
}
209212
}

FirebaseInAppMessaging/Sources/FIRInAppMessaging.m

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#import <FirebaseCore/FIRComponent.h>
2424
#import <FirebaseCore/FIRComponentContainer.h>
2525
#import <FirebaseCore/FIRDependency.h>
26+
#import <FirebaseInstallations/FIRInstallations.h>
2627

2728
#import "FIRCore+InAppMessaging.h"
2829
#import "FIRIAMDisplayExecutor.h"
@@ -62,7 +63,8 @@ + (void)load {
6263
// Ensure it's cached so it returns the same instance every time fiam is called.
6364
*isCacheable = YES;
6465
id<FIRAnalyticsInterop> analytics = FIR_COMPONENT(FIRAnalyticsInterop, container);
65-
return [[FIRInAppMessaging alloc] initWithAnalytics:analytics];
66+
FIRInstallations *installations = [FIRInstallations installationsWithApp:container.app];
67+
return [[FIRInAppMessaging alloc] initWithAnalytics:analytics installations:installations];
6668
};
6769
FIRComponent *fiamProvider =
6870
[FIRComponent componentWithProtocol:@protocol(FIRInAppMessagingInstanceProvider)
@@ -93,10 +95,12 @@ + (void)configureWithApp:(FIRApp *)app {
9395
}
9496
}
9597

96-
- (instancetype)initWithAnalytics:(id<FIRAnalyticsInterop>)analytics {
98+
- (instancetype)initWithAnalytics:(id<FIRAnalyticsInterop>)analytics
99+
installations:(FIRInstallations *)installations {
97100
if (self = [super init]) {
98101
_messageDisplaySuppressed = NO;
99102
_analytics = analytics;
103+
_installations = installations;
100104
}
101105
return self;
102106
}

FirebaseInAppMessaging/Sources/FIRInAppMessagingPrivate.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,15 @@
1818
#import "FIRCore+InAppMessaging.h"
1919
#import "FIRInAppMessaging.h"
2020

21+
@class FIRInstallations;
22+
2123
@protocol FIRInAppMessagingInstanceProvider;
2224
@protocol FIRLibrary;
25+
@protocol FIRAnalyticsInterop;
2326

27+
NS_ASSUME_NONNULL_BEGIN
2428
@interface FIRInAppMessaging () <FIRInAppMessagingInstanceProvider, FIRLibrary>
2529
@property(nonatomic, readwrite, strong) id<FIRAnalyticsInterop> _Nullable analytics;
30+
@property(nonatomic, readwrite, strong) FIRInstallations* _Nullable installations;
2631
@end
32+
NS_ASSUME_NONNULL_END

FirebaseInAppMessaging/Sources/Flows/FIRIAMClientInfoFetcher.m

Lines changed: 57 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -16,52 +16,68 @@
1616

1717
#import <FirebaseCore/FIRAppInternal.h>
1818
#import <FirebaseCore/FIRLogger.h>
19-
#import <FirebaseInstanceID/FirebaseInstanceID.h>
19+
#import <FirebaseInstallations/FirebaseInstallations.h>
2020

2121
#import "FIRCore+InAppMessaging.h"
2222
#import "FIRIAMClientInfoFetcher.h"
23+
#import "FIRIAMSDKRuntimeErrorCodes.h"
24+
#import "FIRInAppMessagingPrivate.h"
25+
26+
@interface FIRIAMClientInfoFetcher ()
27+
28+
@property(nonatomic, strong, nullable, readonly) FIRInstallations *installations;
29+
30+
@end
2331

24-
// declaratons for FIRInstanceID SDK
2532
@implementation FIRIAMClientInfoFetcher
26-
- (void)fetchFirebaseIIDDataWithProjectNumber:(NSString *)projectNumber
27-
withCompletion:(void (^)(NSString *_Nullable iid,
28-
NSString *_Nullable token,
29-
NSError *_Nullable error))completion {
30-
FIRInstanceID *iid = [FIRInstanceID instanceID];
31-
32-
// tokenWithAuthorizedEntity would only communicate with server on periodical cycles.
33-
// For other times, it's going to fetch from local cache, so it's not causing any performance
34-
// concern in the fetch flow.
35-
[iid tokenWithAuthorizedEntity:projectNumber
36-
scope:@"fiam"
37-
options:nil
38-
handler:^(NSString *_Nullable token, NSError *_Nullable error) {
39-
if (error) {
40-
FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM190001",
41-
@"Error in fetching iid token: %@",
42-
error.localizedDescription);
43-
completion(nil, nil, error);
44-
} else {
45-
FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM190002",
46-
@"Successfully generated iid token");
47-
// now we can go ahead to fetch the id
48-
[iid getIDWithHandler:^(NSString *_Nullable identity,
49-
NSError *_Nullable error) {
50-
if (error) {
51-
FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM190004",
52-
@"Error in fetching iid value: %@",
53-
error.localizedDescription);
54-
} else {
55-
FIRLogDebug(
56-
kFIRLoggerInAppMessaging, @"I-IAM190005",
57-
@"Successfully in fetching both iid value as %@ and iid token"
58-
" as %@",
59-
identity, token);
60-
completion(identity, token, nil);
61-
}
62-
}];
63-
}
64-
}];
33+
34+
- (instancetype)initWithFirebaseInstallations:(FIRInstallations *)installations {
35+
if (self = [super init]) {
36+
_installations = installations;
37+
}
38+
return self;
39+
}
40+
41+
- (void)fetchFirebaseInstallationDataWithProjectNumber:(NSString *)projectNumber
42+
withCompletion:
43+
(void (^)(NSString *_Nullable FID,
44+
NSString *_Nullable FISToken,
45+
NSError *_Nullable error))completion {
46+
if (!self.installations) {
47+
NSString *errorDesc = @"Couldn't generate Firebase Installation info";
48+
FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM190010", @"%@", errorDesc);
49+
NSError *error = [NSError errorWithDomain:kFirebaseInAppMessagingErrorDomain
50+
code:FIRIAMSDKRuntimeErrorNoFirebaseInstallationsObject
51+
userInfo:@{NSLocalizedDescriptionKey : errorDesc}];
52+
completion(nil, nil, error);
53+
return;
54+
}
55+
56+
[self.installations authTokenWithCompletion:^(
57+
FIRInstallationsAuthTokenResult *_Nullable tokenResult,
58+
NSError *_Nullable error) {
59+
if (error) {
60+
FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM190006", @"Error in fetching FIS token: %@",
61+
error.localizedDescription);
62+
completion(nil, nil, error);
63+
} else {
64+
FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM190007", @"Successfully generated FIS token");
65+
66+
[self.installations
67+
installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) {
68+
if (error) {
69+
FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM190008", @"Error in fetching FID: %@",
70+
error.localizedDescription);
71+
completion(nil, tokenResult.authToken, error);
72+
} else {
73+
FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM190009",
74+
@"Successfully in fetching both FID as %@ and FIS token as %@",
75+
identifier, tokenResult.authToken);
76+
completion(identifier, tokenResult.authToken, nil);
77+
}
78+
}];
79+
}
80+
}];
6581
}
6682

6783
- (nullable NSString *)getDeviceLanguageCode {

FirebaseInAppMessaging/Sources/Flows/FIRIAMMsgFetcherUsingRestful.m

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ - (void)fetchMessagesWithImpressionList:(NSArray<FIRIAMImpressionRecord *> *)imp
125125

126126
[request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
127127
[request addValue:@"application/json" forHTTPHeaderField:@"Accept"];
128+
[request addValue:iidToken forHTTPHeaderField:@"x-goog-firebase-installations-auth"];
128129

129130
NSMutableDictionary *postFetchDict = [[NSMutableDictionary alloc] init];
130131
[self updatePostFetchData:postFetchDict
@@ -253,21 +254,23 @@ - (void)fetchMessagesWithImpressionList:(NSArray<FIRIAMImpressionRecord *> *)imp
253254
// since the fetch operation frequency is low enough that we are not concerned about its impact
254255
// on server load and this guarantees that we always have an up-to-date iid values and tokens.
255256
[self.clientInfoFetcher
256-
fetchFirebaseIIDDataWithProjectNumber:self.fbProjectNumber
257-
withCompletion:^(NSString *_Nullable iid, NSString *_Nullable token,
258-
NSError *_Nullable error) {
259-
if (error) {
260-
FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM130008",
261-
@"Not able to get iid value and/or token for "
262-
@"talking to server: %@",
263-
error.localizedDescription);
264-
completion(nil, nil, 0, error);
265-
} else {
266-
[self fetchMessagesWithImpressionList:impressonList
267-
withIIDvalue:iid
268-
IIDToken:token
269-
completion:completion];
270-
}
271-
}];
257+
fetchFirebaseInstallationDataWithProjectNumber:self.fbProjectNumber
258+
withCompletion:^(NSString *_Nullable FID,
259+
NSString *_Nullable FISToken,
260+
NSError *_Nullable error) {
261+
if (error) {
262+
FIRLogWarning(
263+
kFIRLoggerInAppMessaging, @"I-IAM130008",
264+
@"Not able to get iid value and/or token for "
265+
@"talking to server: %@",
266+
error.localizedDescription);
267+
completion(nil, nil, 0, error);
268+
} else {
269+
[self fetchMessagesWithImpressionList:impressonList
270+
withIIDvalue:FID
271+
IIDToken:FISToken
272+
completion:completion];
273+
}
274+
}];
272275
}
273276
@end

FirebaseInAppMessaging/Sources/Private/Analytics/FIRIAMClientInfoFetcher.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,25 @@
1616

1717
#import <Foundation/Foundation.h>
1818

19-
// A class for wrapping the interactions for retrieving client side info to be used in request
20-
// parameter for interacting with Firebase iam servers.
19+
@class FIRInstallations;
20+
21+
// A class for wrapping the interactions for retrieving client side info to be used in
22+
// request parameter for interacting with Firebase iam servers.
2123

2224
NS_ASSUME_NONNULL_BEGIN
2325
@interface FIRIAMClientInfoFetcher : NSObject
24-
// Fetch the up-to-date Firebase instance id and token data. Since it involves a server interaction,
25-
// completion callback is provided for receiving the result.
26-
- (void)fetchFirebaseIIDDataWithProjectNumber:(NSString *)projectNumber
27-
withCompletion:(void (^)(NSString *_Nullable iid,
28-
NSString *_Nullable token,
29-
NSError *_Nullable error))completion;
26+
27+
- (instancetype)initWithFirebaseInstallations:(nullable FIRInstallations *)installations;
28+
- (instancetype)init NS_UNAVAILABLE;
29+
30+
// Fetch the up-to-date Firebase Installation ID (FID) and Firebase Installation Service (FIS) token
31+
// data. Since it involves a server interaction, completion callback is provided for receiving the
32+
// result.
33+
- (void)fetchFirebaseInstallationDataWithProjectNumber:(NSString *)projectNumber
34+
withCompletion:
35+
(void (^)(NSString *_Nullable FID,
36+
NSString *_Nullable FISToken,
37+
NSError *_Nullable error))completion;
3038

3139
// Following are synchronous methods for fetching data
3240
- (nullable NSString *)getDeviceLanguageCode;

0 commit comments

Comments
 (0)