SEGContentManager.m 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. // Copyright 2019 Google
  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. #import "FirebaseSegmentation/Sources/SEGContentManager.h"
  15. #import "FirebaseCore/Sources/Private/FIRAppInternal.h"
  16. #import "FirebaseInstallations/Source/Library/Public/FirebaseInstallations/FirebaseInstallations.h"
  17. #import "FirebaseSegmentation/Sources/Public/FIRSegmentation.h"
  18. #import "FirebaseSegmentation/Sources/SEGDatabaseManager.h"
  19. #import "FirebaseSegmentation/Sources/SEGNetworkManager.h"
  20. #import "FirebaseSegmentation/Sources/SEGSegmentationConstants.h"
  21. NSString *const kErrorDescription = @"ErrorDescription";
  22. @interface SEGContentManager () {
  23. NSMutableDictionary<NSString *, id> *_associationData;
  24. NSString *_installationIdentifier;
  25. NSString *_installationIdentifierToken;
  26. SEGDatabaseManager *_databaseManager;
  27. SEGNetworkManager *_networkManager;
  28. }
  29. @end
  30. @implementation SEGContentManager
  31. + (instancetype)sharedInstanceWithOptions:(FIROptions *)options {
  32. static dispatch_once_t onceToken;
  33. static SEGContentManager *sharedInstance;
  34. dispatch_once(&onceToken, ^{
  35. sharedInstance = [[SEGContentManager alloc]
  36. initWithDatabaseManager:[SEGDatabaseManager sharedInstance]
  37. networkManager:[[SEGNetworkManager alloc] initWithFIROptions:options]];
  38. });
  39. return sharedInstance;
  40. }
  41. - (instancetype)initWithDatabaseManager:databaseManager networkManager:networkManager {
  42. self = [super init];
  43. if (self) {
  44. // Initialize the database manager.
  45. _databaseManager = databaseManager;
  46. // Initialize the network manager.
  47. _networkManager = networkManager;
  48. // Load all data from the database.
  49. [_databaseManager createOrOpenDatabaseWithCompletion:^(BOOL success, NSDictionary *result) {
  50. self->_associationData = [result mutableCopy];
  51. }];
  52. // TODO(dmandar) subscribe to FIS notifications once integrated.
  53. }
  54. return self;
  55. }
  56. - (FIRInstallations *)installationForApp:(NSString *)firebaseApp {
  57. return [FIRInstallations installationsWithApp:[FIRApp appNamed:firebaseApp]];
  58. }
  59. - (void)associateCustomInstallationIdentiferNamed:(NSString *)customInstallationID
  60. firebaseApp:(NSString *)firebaseApp
  61. completion:(SEGRequestCompletion)completionHandler {
  62. // Get the latest installation identifier
  63. FIRInstallations *installation = [self installationForApp:firebaseApp];
  64. if (installation == nil) {
  65. completionHandler(NO, @{kErrorDescription : @"Firebase Installations SDK not available"});
  66. }
  67. __weak SEGContentManager *weakSelf = self;
  68. [installation
  69. installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) {
  70. SEGContentManager *strongSelf = weakSelf;
  71. if (!strongSelf) {
  72. completionHandler(NO, @{kErrorDescription : @"Internal Error getting installation ID."});
  73. return;
  74. }
  75. [strongSelf associateInstallationWithLatestIdentifier:identifier
  76. installation:installation
  77. customizedIdentifier:customInstallationID
  78. firebaseApp:firebaseApp
  79. error:error
  80. completion:completionHandler];
  81. }];
  82. }
  83. - (void)associateInstallationWithLatestIdentifier:(NSString *_Nullable)identifier
  84. installation:(FIRInstallations *)installation
  85. customizedIdentifier:(NSString *)customInstallationID
  86. firebaseApp:(NSString *)firebaseApp
  87. error:(NSError *_Nullable)error
  88. completion:(SEGRequestCompletion)completionHandler {
  89. if (!identifier || error) {
  90. NSString *errorMessage = @"Error getting installation ID.";
  91. if (error) {
  92. errorMessage = [errorMessage stringByAppendingString:error.description];
  93. }
  94. NSDictionary *errorDictionary = @{kErrorDescription : errorMessage};
  95. completionHandler(NO, errorDictionary);
  96. return;
  97. }
  98. _installationIdentifier = identifier;
  99. __weak SEGContentManager *weakSelf = self;
  100. [installation authTokenWithCompletion:^(FIRInstallationsAuthTokenResult *_Nullable tokenResult,
  101. NSError *_Nullable error) {
  102. SEGContentManager *strongSelf = weakSelf;
  103. if (!strongSelf) {
  104. completionHandler(NO, @{kErrorDescription : @"Internal Error getting installation token."});
  105. return;
  106. }
  107. [strongSelf associateInstallationWithToken:tokenResult
  108. customizedIdentifier:customInstallationID
  109. firebaseApp:firebaseApp
  110. error:error
  111. completion:completionHandler];
  112. }];
  113. }
  114. - (void)associateInstallationWithToken:(FIRInstallationsAuthTokenResult *_Nullable)tokenResult
  115. customizedIdentifier:(NSString *)customInstallationID
  116. firebaseApp:(NSString *)firebaseApp
  117. error:(NSError *_Nullable)error
  118. completion:(SEGRequestCompletion)completionHandler {
  119. if (!tokenResult || error) {
  120. NSString *errorMessage = @"Error getting AuthToken.";
  121. if (error) {
  122. errorMessage = [errorMessage stringByAppendingString:error.description];
  123. }
  124. NSDictionary *errorDictionary = @{kErrorDescription : errorMessage};
  125. completionHandler(NO, errorDictionary);
  126. return;
  127. }
  128. _installationIdentifierToken = tokenResult.authToken;
  129. NSMutableDictionary<NSString *, NSString *> *appAssociationData =
  130. [[NSMutableDictionary alloc] init];
  131. appAssociationData[kSEGCustomInstallationIdentifierKey] = customInstallationID;
  132. appAssociationData[kSEGFirebaseInstallationIdentifierKey] = _installationIdentifier;
  133. appAssociationData[kSEGAssociationStatusKey] = kSEGAssociationStatusPending;
  134. _associationData[firebaseApp] = appAssociationData;
  135. // Update the database async.
  136. // TODO(mandard) The database write and corresponding completion handler needs to be wired up
  137. // once we support listening to FID changes.
  138. [_databaseManager insertMainTableApplicationNamed:firebaseApp
  139. customInstanceIdentifier:customInstallationID
  140. firebaseInstanceIdentifier:_installationIdentifier
  141. associationStatus:kSEGAssociationStatusPending
  142. completionHandler:nil];
  143. // Send the change up to the backend. Also add the token.
  144. [_networkManager
  145. makeAssociationRequestToBackendWithData:appAssociationData
  146. token:_installationIdentifierToken
  147. completion:^(BOOL status, NSDictionary<NSString *, id> *result) {
  148. // TODO...log, update database.
  149. completionHandler(status, result);
  150. }];
  151. }
  152. @end