FIRDatabaseComponent.m 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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/Public/FirebaseAuthInterop/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. FIRComponentCreationBlock creationBlock =
  50. ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) {
  51. *isCacheable = YES;
  52. return [[FIRDatabaseComponent alloc] initWithApp:container.app];
  53. };
  54. FIRComponent *databaseProvider =
  55. [FIRComponent componentWithProtocol:@protocol(FIRDatabaseProvider)
  56. instantiationTiming:FIRInstantiationTimingLazy
  57. creationBlock:creationBlock];
  58. return @[ databaseProvider ];
  59. }
  60. #pragma mark - Instance management.
  61. - (void)appWillBeDeleted:(FIRApp *)app {
  62. NSString *appName = app.name;
  63. if (appName == nil) {
  64. return;
  65. }
  66. FIRDatabaseDictionary *instances = [self instances];
  67. @synchronized(instances) {
  68. // Clean up the deleted instance in an effort to remove any resources
  69. // still in use. Note: Any leftover instances of this exact database
  70. // will be invalid.
  71. for (FIRDatabase *database in [instances allValues]) {
  72. [FRepoManager disposeRepos:database.config];
  73. }
  74. [instances removeAllObjects];
  75. }
  76. }
  77. #pragma mark - FIRDatabaseProvider Conformance
  78. - (FIRDatabase *)databaseForApp:(FIRApp *)app URL:(NSString *)url {
  79. if (app == nil) {
  80. [NSException raise:@"InvalidFIRApp"
  81. format:@"nil FIRApp instance passed to databaseForApp."];
  82. }
  83. if (url == nil) {
  84. [NSException raise:@"MissingDatabaseURL"
  85. format:@"Failed to get FirebaseDatabase instance: "
  86. "Specify DatabaseURL within FIRApp or from your "
  87. "databaseForApp:URL: call."];
  88. }
  89. NSURL *databaseUrl = [NSURL URLWithString:url];
  90. if (databaseUrl == nil) {
  91. [NSException raise:@"InvalidDatabaseURL"
  92. format:@"The Database URL '%@' cannot be parsed. "
  93. "Specify a valid DatabaseURL within FIRApp or from "
  94. "your databaseForApp:URL: call.",
  95. url];
  96. } else if (![databaseUrl.path isEqualToString:@""] &&
  97. ![databaseUrl.path isEqualToString:@"/"]) {
  98. [NSException
  99. raise:@"InvalidDatabaseURL"
  100. format:@"Configured Database URL '%@' is invalid. It should point "
  101. "to the root of a Firebase Database but it includes a "
  102. "path: %@",
  103. databaseUrl, databaseUrl.path];
  104. }
  105. FIRDatabaseDictionary *instances = [self instances];
  106. @synchronized(instances) {
  107. FParsedUrl *parsedUrl =
  108. [FUtilities parseUrl:databaseUrl.absoluteString];
  109. NSString *urlIndex =
  110. [NSString stringWithFormat:@"%@:%@", parsedUrl.repoInfo.host,
  111. [parsedUrl.path toString]];
  112. FIRDatabase *database = instances[urlIndex];
  113. if (!database) {
  114. id<FIRDatabaseConnectionContextProvider> contextProvider =
  115. [FIRDatabaseConnectionContextProvider
  116. contextProviderWithAuth:FIR_COMPONENT(FIRAuthInterop,
  117. app.container)
  118. appCheck:FIR_COMPONENT(FIRAppCheckInterop,
  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. contextProvider:contextProvider];
  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