FIRDatabaseComponent.m 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. * Copyright 2018 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import "FirebaseDatabase/Sources/Api/FIRDatabaseComponent.h"
  17. #import "FirebaseDatabase/Sources/Api/Private/FIRDatabase_Private.h"
  18. #import "FirebaseDatabase/Sources/Core/FRepoManager.h"
  19. #import "FirebaseDatabase/Sources/FIRDatabaseConfig_Private.h"
  20. #import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"
  21. #import "Interop/Auth/Public/FIRAuthInterop.h"
  22. NS_ASSUME_NONNULL_BEGIN
  23. /** A NSMutableDictionary of FirebaseApp name and FRepoInfo to FirebaseDatabase
  24. * instance. */
  25. typedef NSMutableDictionary<NSString *, FIRDatabase *> FIRDatabaseDictionary;
  26. @interface FIRDatabaseComponent () <FIRComponentLifecycleMaintainer, FIRLibrary>
  27. @property(nonatomic) FIRDatabaseDictionary *instances;
  28. /// Internal intializer.
  29. - (instancetype)initWithApp:(FIRApp *)app;
  30. @end
  31. @implementation FIRDatabaseComponent
  32. #pragma mark - Initialization
  33. - (instancetype)initWithApp:(FIRApp *)app {
  34. self = [super init];
  35. if (self) {
  36. _app = app;
  37. _instances = [NSMutableDictionary dictionary];
  38. }
  39. return self;
  40. }
  41. #pragma mark - Lifecycle
  42. + (void)load {
  43. [FIRApp registerInternalLibrary:(Class<FIRLibrary>)self
  44. withName:@"fire-db"];
  45. }
  46. #pragma mark - FIRComponentRegistrant
  47. + (NSArray<FIRComponent *> *)componentsToRegister {
  48. FIRDependency *authDep =
  49. [FIRDependency dependencyWithProtocol:@protocol(FIRAuthInterop)
  50. isRequired:NO];
  51. FIRComponentCreationBlock creationBlock =
  52. ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) {
  53. *isCacheable = YES;
  54. return [[FIRDatabaseComponent alloc] initWithApp:container.app];
  55. };
  56. FIRComponent *databaseProvider =
  57. [FIRComponent componentWithProtocol:@protocol(FIRDatabaseProvider)
  58. instantiationTiming:FIRInstantiationTimingLazy
  59. dependencies:@[ authDep ]
  60. creationBlock:creationBlock];
  61. return @[ databaseProvider ];
  62. }
  63. #pragma mark - Instance management.
  64. - (void)appWillBeDeleted:(FIRApp *)app {
  65. NSString *appName = app.name;
  66. if (appName == nil) {
  67. return;
  68. }
  69. FIRDatabaseDictionary *instances = [self instances];
  70. @synchronized(instances) {
  71. // Clean up the deleted instance in an effort to remove any resources
  72. // still in use. Note: Any leftover instances of this exact database
  73. // will be invalid.
  74. for (FIRDatabase *database in [instances allValues]) {
  75. [FRepoManager disposeRepos:database.config];
  76. }
  77. [instances removeAllObjects];
  78. }
  79. }
  80. #pragma mark - FIRDatabaseProvider Conformance
  81. - (FIRDatabase *)databaseForApp:(FIRApp *)app URL:(NSString *)url {
  82. if (app == nil) {
  83. [NSException raise:@"InvalidFIRApp"
  84. format:@"nil FIRApp instance passed to databaseForApp."];
  85. }
  86. if (url == nil) {
  87. [NSException raise:@"MissingDatabaseURL"
  88. format:@"Failed to get FirebaseDatabase instance: "
  89. "Specify DatabaseURL within FIRApp or from your "
  90. "databaseForApp:URL: call."];
  91. }
  92. NSURL *databaseUrl = [NSURL URLWithString:url];
  93. if (databaseUrl == nil) {
  94. [NSException raise:@"InvalidDatabaseURL"
  95. format:@"The Database URL '%@' cannot be parsed. "
  96. "Specify a valid DatabaseURL within FIRApp or from "
  97. "your databaseForApp:URL: call.",
  98. url];
  99. } else if (![databaseUrl.path isEqualToString:@""] &&
  100. ![databaseUrl.path isEqualToString:@"/"]) {
  101. [NSException
  102. raise:@"InvalidDatabaseURL"
  103. format:@"Configured Database URL '%@' is invalid. It should point "
  104. "to the root of a Firebase Database but it includes a "
  105. "path: %@",
  106. databaseUrl, databaseUrl.path];
  107. }
  108. FIRDatabaseDictionary *instances = [self instances];
  109. @synchronized(instances) {
  110. FParsedUrl *parsedUrl =
  111. [FUtilities parseUrl:databaseUrl.absoluteString];
  112. NSString *urlIndex =
  113. [NSString stringWithFormat:@"%@:%@", parsedUrl.repoInfo.host,
  114. [parsedUrl.path toString]];
  115. FIRDatabase *database = instances[urlIndex];
  116. if (!database) {
  117. id<FAuthTokenProvider> authTokenProvider = [FAuthTokenProvider
  118. authTokenProviderWithAuth:FIR_COMPONENT(FIRAuthInterop,
  119. app.container)];
  120. // If this is the default app, don't set the session persistence key
  121. // so that we use our default ("default") instead of the FIRApp
  122. // default ("[DEFAULT]") so that we preserve the default location
  123. // used by the legacy Firebase SDK.
  124. NSString *sessionIdentifier = @"default";
  125. if (![FIRApp isDefaultAppConfigured] ||
  126. app != [FIRApp defaultApp]) {
  127. sessionIdentifier = app.name;
  128. }
  129. FIRDatabaseConfig *config = [[FIRDatabaseConfig alloc]
  130. initWithSessionIdentifier:sessionIdentifier
  131. googleAppID:app.options.googleAppID
  132. authTokenProvider:authTokenProvider];
  133. database = [[FIRDatabase alloc] initWithApp:app
  134. repoInfo:parsedUrl.repoInfo
  135. config:config];
  136. instances[urlIndex] = database;
  137. }
  138. return database;
  139. }
  140. }
  141. @end
  142. NS_ASSUME_NONNULL_END