FIRDatabaseComponent.m 5.5 KB

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