RLMSyncManager.mm 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 Realm Inc.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. //
  17. ////////////////////////////////////////////////////////////////////////////
  18. #import "RLMSyncManager_Private.h"
  19. #import "RLMRealmConfiguration+Sync.h"
  20. #import "RLMSyncConfiguration_Private.hpp"
  21. #import "RLMSyncSession_Private.hpp"
  22. #import "RLMSyncUser_Private.hpp"
  23. #import "RLMSyncUtil_Private.hpp"
  24. #import "RLMUtil.hpp"
  25. #import "sync/sync_config.hpp"
  26. #import "sync/sync_manager.hpp"
  27. #import "sync/sync_session.hpp"
  28. #if !defined(REALM_COCOA_VERSION)
  29. #import "RLMVersion.h"
  30. #endif
  31. using namespace realm;
  32. using Level = realm::util::Logger::Level;
  33. namespace {
  34. Level levelForSyncLogLevel(RLMSyncLogLevel logLevel) {
  35. switch (logLevel) {
  36. case RLMSyncLogLevelOff: return Level::off;
  37. case RLMSyncLogLevelFatal: return Level::fatal;
  38. case RLMSyncLogLevelError: return Level::error;
  39. case RLMSyncLogLevelWarn: return Level::warn;
  40. case RLMSyncLogLevelInfo: return Level::info;
  41. case RLMSyncLogLevelDetail: return Level::detail;
  42. case RLMSyncLogLevelDebug: return Level::debug;
  43. case RLMSyncLogLevelTrace: return Level::trace;
  44. case RLMSyncLogLevelAll: return Level::all;
  45. }
  46. REALM_UNREACHABLE(); // Unrecognized log level.
  47. }
  48. RLMSyncLogLevel logLevelForLevel(Level logLevel) {
  49. switch (logLevel) {
  50. case Level::off: return RLMSyncLogLevelOff;
  51. case Level::fatal: return RLMSyncLogLevelFatal;
  52. case Level::error: return RLMSyncLogLevelError;
  53. case Level::warn: return RLMSyncLogLevelWarn;
  54. case Level::info: return RLMSyncLogLevelInfo;
  55. case Level::detail: return RLMSyncLogLevelDetail;
  56. case Level::debug: return RLMSyncLogLevelDebug;
  57. case Level::trace: return RLMSyncLogLevelTrace;
  58. case Level::all: return RLMSyncLogLevelAll;
  59. }
  60. REALM_UNREACHABLE(); // Unrecognized log level.
  61. }
  62. struct CocoaSyncLogger : public realm::util::RootLogger {
  63. void do_log(Level, std::string message) override {
  64. NSLog(@"Sync: %@", RLMStringDataToNSString(message));
  65. }
  66. };
  67. struct CocoaSyncLoggerFactory : public realm::SyncLoggerFactory {
  68. std::unique_ptr<realm::util::Logger> make_logger(realm::util::Logger::Level level) override {
  69. auto logger = std::make_unique<CocoaSyncLogger>();
  70. logger->set_level_threshold(level);
  71. return std::move(logger);
  72. }
  73. } s_syncLoggerFactory;
  74. } // anonymous namespace
  75. @interface RLMSyncManager ()
  76. - (instancetype)initWithCustomRootDirectory:(nullable NSURL *)rootDirectory NS_DESIGNATED_INITIALIZER;
  77. @end
  78. @implementation RLMSyncManager
  79. static RLMSyncManager *s_sharedManager = nil;
  80. + (instancetype)sharedManager {
  81. static std::once_flag flag;
  82. std::call_once(flag, [] {
  83. try {
  84. s_sharedManager = [[RLMSyncManager alloc] initWithCustomRootDirectory:nil];
  85. }
  86. catch (std::exception const& e) {
  87. @throw RLMException(e);
  88. }
  89. });
  90. return s_sharedManager;
  91. }
  92. - (instancetype)initWithCustomRootDirectory:(NSURL *)rootDirectory {
  93. if (self = [super init]) {
  94. [RLMSyncUser _setUpBindingContextFactory];
  95. // Initialize the sync engine.
  96. SyncManager::shared().set_logger_factory(s_syncLoggerFactory);
  97. bool should_encrypt = !getenv("REALM_DISABLE_METADATA_ENCRYPTION") && !RLMIsRunningInPlayground();
  98. auto mode = should_encrypt ? SyncManager::MetadataMode::Encryption : SyncManager::MetadataMode::NoEncryption;
  99. rootDirectory = rootDirectory ?: [NSURL fileURLWithPath:RLMDefaultDirectoryForBundleIdentifier(nil)];
  100. @autoreleasepool {
  101. bool isSwift = !!NSClassFromString(@"RealmSwiftObjectUtil");
  102. auto userAgent = [[NSMutableString alloc] initWithFormat:@"Realm%@/%@",
  103. isSwift ? @"Swift" : @"ObjectiveC", REALM_COCOA_VERSION];
  104. SyncManager::shared().configure(rootDirectory.path.UTF8String, mode, RLMStringDataWithNSString(userAgent), none, true);
  105. SyncManager::shared().set_user_agent(RLMStringDataWithNSString(self.appID));
  106. }
  107. return self;
  108. }
  109. return nil;
  110. }
  111. - (NSString *)appID {
  112. if (!_appID) {
  113. _appID = [[NSBundle mainBundle] bundleIdentifier] ?: @"(none)";
  114. }
  115. return _appID;
  116. }
  117. - (void)setUserAgent:(NSString *)userAgent {
  118. SyncManager::shared().set_user_agent(RLMStringDataWithNSString(userAgent));
  119. _userAgent = userAgent;
  120. }
  121. #pragma mark - Passthrough properties
  122. - (RLMSyncLogLevel)logLevel {
  123. return logLevelForLevel(realm::SyncManager::shared().log_level());
  124. }
  125. - (void)setLogLevel:(RLMSyncLogLevel)logLevel {
  126. realm::SyncManager::shared().set_log_level(levelForSyncLogLevel(logLevel));
  127. }
  128. #pragma mark - Private API
  129. - (void)_fireError:(NSError *)error {
  130. dispatch_async(dispatch_get_main_queue(), ^{
  131. if (self.errorHandler) {
  132. self.errorHandler(error, nil);
  133. }
  134. });
  135. }
  136. - (void)_fireErrorWithCode:(int)errorCode
  137. message:(NSString *)message
  138. isFatal:(BOOL)fatal
  139. session:(RLMSyncSession *)session
  140. userInfo:(NSDictionary *)userInfo
  141. errorClass:(RLMSyncSystemErrorKind)errorClass {
  142. NSError *error = nil;
  143. BOOL shouldMakeError = YES;
  144. NSDictionary *custom = nil;
  145. // Note that certain types of errors are 'interactive'; users have several options
  146. // as to how to proceed after the error is reported.
  147. switch (errorClass) {
  148. case RLMSyncSystemErrorKindClientReset: {
  149. std::string path = [userInfo[@(realm::SyncError::c_original_file_path_key)] UTF8String];
  150. custom = @{kRLMSyncPathOfRealmBackupCopyKey:
  151. userInfo[@(realm::SyncError::c_recovery_file_path_key)],
  152. kRLMSyncErrorActionTokenKey:
  153. [[RLMSyncErrorActionToken alloc] initWithOriginalPath:std::move(path)]
  154. };;
  155. break;
  156. }
  157. case RLMSyncSystemErrorKindPermissionDenied: {
  158. std::string path = [userInfo[@(realm::SyncError::c_original_file_path_key)] UTF8String];
  159. custom = @{kRLMSyncErrorActionTokenKey:
  160. [[RLMSyncErrorActionToken alloc] initWithOriginalPath:std::move(path)]
  161. };
  162. break;
  163. }
  164. case RLMSyncSystemErrorKindUser:
  165. case RLMSyncSystemErrorKindSession:
  166. break;
  167. case RLMSyncSystemErrorKindConnection:
  168. case RLMSyncSystemErrorKindClient:
  169. case RLMSyncSystemErrorKindUnknown:
  170. // Report the error. There's nothing the user can do about it, though.
  171. shouldMakeError = fatal;
  172. break;
  173. }
  174. error = shouldMakeError ? make_sync_error(errorClass, message, errorCode, custom) : nil;
  175. dispatch_async(dispatch_get_main_queue(), ^{
  176. if (!self.errorHandler || !error) {
  177. return;
  178. }
  179. self.errorHandler(error, session);
  180. });
  181. }
  182. - (NSArray<RLMSyncUser *> *)_allUsers {
  183. NSMutableArray<RLMSyncUser *> *buffer = [NSMutableArray array];
  184. for (auto user : SyncManager::shared().all_logged_in_users()) {
  185. [buffer addObject:[[RLMSyncUser alloc] initWithSyncUser:std::move(user)]];
  186. }
  187. return buffer;
  188. }
  189. + (void)resetForTesting {
  190. SyncManager::shared().reset_for_testing();
  191. }
  192. - (RLMNetworkRequestOptions *)networkRequestOptions {
  193. RLMNetworkRequestOptions *options = [[RLMNetworkRequestOptions alloc] init];
  194. options.authorizationHeaderName = self.authorizationHeaderName;
  195. options.customHeaders = self.customRequestHeaders;
  196. options.pinnedCertificatePaths = self.pinnedCertificatePaths;
  197. return options;
  198. }
  199. @end