FIRDatabaseComponent.m 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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 "FirebaseAuth/Interop/FIRAuthInterop.h"
  21. #import "FirebaseCore/Extension/FirebaseCoreInternal.h"
  22. #import <FirebaseAppCheckInterop/FirebaseAppCheckInterop.h>
  23. NS_ASSUME_NONNULL_BEGIN
  24. /** A NSMutableDictionary of FirebaseApp name and FRepoInfo to FirebaseDatabase
  25. * instance. */
  26. typedef NSMutableDictionary<NSString *, FIRDatabase *> FIRDatabaseDictionary;
  27. @interface FIRDatabaseComponent () <FIRComponentLifecycleMaintainer, FIRLibrary>
  28. @property(nonatomic) FIRDatabaseDictionary *instances;
  29. /// Internal initializer.
  30. - (instancetype)initWithApp:(FIRApp *)app;
  31. @end
  32. @implementation FIRDatabaseComponent
  33. #pragma mark - Initialization
  34. - (instancetype)initWithApp:(FIRApp *)app {
  35. self = [super init];
  36. if (self) {
  37. _app = app;
  38. _instances = [NSMutableDictionary dictionary];
  39. }
  40. return self;
  41. }
  42. #pragma mark - Lifecycle
  43. + (void)load {
  44. [FIRApp registerInternalLibrary:(Class<FIRLibrary>)self
  45. withName:@"fire-db"];
  46. }
  47. #pragma mark - FIRComponentRegistrant
  48. + (NSArray<FIRComponent *> *)componentsToRegister {
  49. FIRDependency *authDep =
  50. [FIRDependency dependencyWithProtocol:@protocol(FIRAuthInterop)
  51. isRequired:NO];
  52. FIRComponentCreationBlock creationBlock =
  53. ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) {
  54. *isCacheable = YES;
  55. return [[FIRDatabaseComponent alloc] initWithApp:container.app];
  56. };
  57. FIRComponent *databaseProvider =
  58. [FIRComponent componentWithProtocol:@protocol(FIRDatabaseProvider)
  59. instantiationTiming:FIRInstantiationTimingLazy
  60. dependencies:@[ authDep ]
  61. creationBlock:creationBlock];
  62. return @[ databaseProvider ];
  63. }
  64. #pragma mark - Instance management.
  65. - (void)appWillBeDeleted:(FIRApp *)app {
  66. NSString *appName = app.name;
  67. if (appName == nil) {
  68. return;
  69. }
  70. FIRDatabaseDictionary *instances = [self instances];
  71. @synchronized(instances) {
  72. // Clean up the deleted instance in an effort to remove any resources
  73. // still in use. Note: Any leftover instances of this exact database
  74. // will be invalid.
  75. for (FIRDatabase *database in [instances allValues]) {
  76. [FRepoManager disposeRepos:database.config];
  77. }
  78. [instances removeAllObjects];
  79. }
  80. }
  81. #pragma mark - FIRDatabaseProvider Conformance
  82. - (FIRDatabase *)databaseForApp:(FIRApp *)app URL:(NSString *)url {
  83. if (app == nil) {
  84. [NSException raise:@"InvalidFIRApp"
  85. format:@"nil FIRApp instance passed to databaseForApp."];
  86. }
  87. if (url == nil) {
  88. [NSException raise:@"MissingDatabaseURL"
  89. format:@"Failed to get FirebaseDatabase instance: "
  90. "Specify DatabaseURL within FIRApp or from your "
  91. "databaseForApp:URL: call."];
  92. }
  93. NSURL *databaseUrl = [NSURL URLWithString:url];
  94. if (databaseUrl == nil) {
  95. [NSException raise:@"InvalidDatabaseURL"
  96. format:@"The Database URL '%@' cannot be parsed. "
  97. "Specify a valid DatabaseURL within FIRApp or from "
  98. "your databaseForApp:URL: call.",
  99. url];
  100. } else if (![databaseUrl.path isEqualToString:@""] &&
  101. ![databaseUrl.path isEqualToString:@"/"]) {
  102. [NSException
  103. raise:@"InvalidDatabaseURL"
  104. format:@"Configured Database URL '%@' is invalid. It should point "
  105. "to the root of a Firebase Database but it includes a "
  106. "path: %@",
  107. databaseUrl, databaseUrl.path];
  108. }
  109. FIRDatabaseDictionary *instances = [self instances];
  110. @synchronized(instances) {
  111. FParsedUrl *parsedUrl =
  112. [FUtilities parseUrl:databaseUrl.absoluteString];
  113. NSString *urlIndex =
  114. [NSString stringWithFormat:@"%@:%@", parsedUrl.repoInfo.host,
  115. [parsedUrl.path toString]];
  116. FIRDatabase *database = instances[urlIndex];
  117. if (!database) {
  118. id<FIRDatabaseConnectionContextProvider> contextProvider =
  119. [FIRDatabaseConnectionContextProvider
  120. contextProviderWithAuth:FIR_COMPONENT(FIRAuthInterop,
  121. app.container)
  122. appCheck:FIR_COMPONENT(FIRAppCheckInterop,
  123. app.container)];
  124. // If this is the default app, don't set the session persistence key
  125. // so that we use our default ("default") instead of the FIRApp
  126. // default ("[DEFAULT]") so that we preserve the default location
  127. // used by the legacy Firebase SDK.
  128. NSString *sessionIdentifier = @"default";
  129. if (![FIRApp isDefaultAppConfigured] ||
  130. app != [FIRApp defaultApp]) {
  131. sessionIdentifier = app.name;
  132. }
  133. FIRDatabaseConfig *config = [[FIRDatabaseConfig alloc]
  134. initWithSessionIdentifier:sessionIdentifier
  135. googleAppID:app.options.googleAppID
  136. contextProvider:contextProvider];
  137. database = [[FIRDatabase alloc] initWithApp:app
  138. repoInfo:parsedUrl.repoInfo
  139. config:config];
  140. instances[urlIndex] = database;
  141. }
  142. return database;
  143. }
  144. }
  145. @end
  146. NS_ASSUME_NONNULL_END