SEGContentManager.m 7.1 KB

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