123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- ////////////////////////////////////////////////////////////////////////////
- //
- // Copyright 2016 Realm Inc.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- //
- ////////////////////////////////////////////////////////////////////////////
- #import "RLMSyncManager_Private.h"
- #import "RLMRealmConfiguration+Sync.h"
- #import "RLMSyncConfiguration_Private.hpp"
- #import "RLMSyncSession_Private.hpp"
- #import "RLMSyncUser_Private.hpp"
- #import "RLMSyncUtil_Private.hpp"
- #import "RLMUtil.hpp"
- #import "sync/sync_config.hpp"
- #import "sync/sync_manager.hpp"
- #import "sync/sync_session.hpp"
- #if !defined(REALM_COCOA_VERSION)
- #import "RLMVersion.h"
- #endif
- using namespace realm;
- using Level = realm::util::Logger::Level;
- namespace {
- Level levelForSyncLogLevel(RLMSyncLogLevel logLevel) {
- switch (logLevel) {
- case RLMSyncLogLevelOff: return Level::off;
- case RLMSyncLogLevelFatal: return Level::fatal;
- case RLMSyncLogLevelError: return Level::error;
- case RLMSyncLogLevelWarn: return Level::warn;
- case RLMSyncLogLevelInfo: return Level::info;
- case RLMSyncLogLevelDetail: return Level::detail;
- case RLMSyncLogLevelDebug: return Level::debug;
- case RLMSyncLogLevelTrace: return Level::trace;
- case RLMSyncLogLevelAll: return Level::all;
- }
- REALM_UNREACHABLE(); // Unrecognized log level.
- }
- RLMSyncLogLevel logLevelForLevel(Level logLevel) {
- switch (logLevel) {
- case Level::off: return RLMSyncLogLevelOff;
- case Level::fatal: return RLMSyncLogLevelFatal;
- case Level::error: return RLMSyncLogLevelError;
- case Level::warn: return RLMSyncLogLevelWarn;
- case Level::info: return RLMSyncLogLevelInfo;
- case Level::detail: return RLMSyncLogLevelDetail;
- case Level::debug: return RLMSyncLogLevelDebug;
- case Level::trace: return RLMSyncLogLevelTrace;
- case Level::all: return RLMSyncLogLevelAll;
- }
- REALM_UNREACHABLE(); // Unrecognized log level.
- }
- struct CocoaSyncLogger : public realm::util::RootLogger {
- void do_log(Level, std::string message) override {
- NSLog(@"Sync: %@", RLMStringDataToNSString(message));
- }
- };
- struct CocoaSyncLoggerFactory : public realm::SyncLoggerFactory {
- std::unique_ptr<realm::util::Logger> make_logger(realm::util::Logger::Level level) override {
- auto logger = std::make_unique<CocoaSyncLogger>();
- logger->set_level_threshold(level);
- return std::move(logger);
- }
- } s_syncLoggerFactory;
- } // anonymous namespace
- @interface RLMSyncManager ()
- - (instancetype)initWithCustomRootDirectory:(nullable NSURL *)rootDirectory NS_DESIGNATED_INITIALIZER;
- @end
- @implementation RLMSyncManager
- static RLMSyncManager *s_sharedManager = nil;
- + (instancetype)sharedManager {
- static std::once_flag flag;
- std::call_once(flag, [] {
- try {
- s_sharedManager = [[RLMSyncManager alloc] initWithCustomRootDirectory:nil];
- }
- catch (std::exception const& e) {
- @throw RLMException(e);
- }
- });
- return s_sharedManager;
- }
- - (instancetype)initWithCustomRootDirectory:(NSURL *)rootDirectory {
- if (self = [super init]) {
- [RLMSyncUser _setUpBindingContextFactory];
- // Initialize the sync engine.
- SyncManager::shared().set_logger_factory(s_syncLoggerFactory);
- bool should_encrypt = !getenv("REALM_DISABLE_METADATA_ENCRYPTION") && !RLMIsRunningInPlayground();
- auto mode = should_encrypt ? SyncManager::MetadataMode::Encryption : SyncManager::MetadataMode::NoEncryption;
- rootDirectory = rootDirectory ?: [NSURL fileURLWithPath:RLMDefaultDirectoryForBundleIdentifier(nil)];
- @autoreleasepool {
- bool isSwift = !!NSClassFromString(@"RealmSwiftObjectUtil");
- auto userAgent = [[NSMutableString alloc] initWithFormat:@"Realm%@/%@",
- isSwift ? @"Swift" : @"ObjectiveC", REALM_COCOA_VERSION];
- SyncManager::shared().configure(rootDirectory.path.UTF8String, mode, RLMStringDataWithNSString(userAgent), none, true);
- SyncManager::shared().set_user_agent(RLMStringDataWithNSString(self.appID));
- }
- return self;
- }
- return nil;
- }
- - (NSString *)appID {
- if (!_appID) {
- _appID = [[NSBundle mainBundle] bundleIdentifier] ?: @"(none)";
- }
- return _appID;
- }
- - (void)setUserAgent:(NSString *)userAgent {
- SyncManager::shared().set_user_agent(RLMStringDataWithNSString(userAgent));
- _userAgent = userAgent;
- }
- #pragma mark - Passthrough properties
- - (RLMSyncLogLevel)logLevel {
- return logLevelForLevel(realm::SyncManager::shared().log_level());
- }
- - (void)setLogLevel:(RLMSyncLogLevel)logLevel {
- realm::SyncManager::shared().set_log_level(levelForSyncLogLevel(logLevel));
- }
- #pragma mark - Private API
- - (void)_fireError:(NSError *)error {
- dispatch_async(dispatch_get_main_queue(), ^{
- if (self.errorHandler) {
- self.errorHandler(error, nil);
- }
- });
- }
- - (void)_fireErrorWithCode:(int)errorCode
- message:(NSString *)message
- isFatal:(BOOL)fatal
- session:(RLMSyncSession *)session
- userInfo:(NSDictionary *)userInfo
- errorClass:(RLMSyncSystemErrorKind)errorClass {
- NSError *error = nil;
- BOOL shouldMakeError = YES;
- NSDictionary *custom = nil;
- // Note that certain types of errors are 'interactive'; users have several options
- // as to how to proceed after the error is reported.
- switch (errorClass) {
- case RLMSyncSystemErrorKindClientReset: {
- std::string path = [userInfo[@(realm::SyncError::c_original_file_path_key)] UTF8String];
- custom = @{kRLMSyncPathOfRealmBackupCopyKey:
- userInfo[@(realm::SyncError::c_recovery_file_path_key)],
- kRLMSyncErrorActionTokenKey:
- [[RLMSyncErrorActionToken alloc] initWithOriginalPath:std::move(path)]
- };;
- break;
- }
- case RLMSyncSystemErrorKindPermissionDenied: {
- std::string path = [userInfo[@(realm::SyncError::c_original_file_path_key)] UTF8String];
- custom = @{kRLMSyncErrorActionTokenKey:
- [[RLMSyncErrorActionToken alloc] initWithOriginalPath:std::move(path)]
- };
- break;
- }
- case RLMSyncSystemErrorKindUser:
- case RLMSyncSystemErrorKindSession:
- break;
- case RLMSyncSystemErrorKindConnection:
- case RLMSyncSystemErrorKindClient:
- case RLMSyncSystemErrorKindUnknown:
- // Report the error. There's nothing the user can do about it, though.
- shouldMakeError = fatal;
- break;
- }
- error = shouldMakeError ? make_sync_error(errorClass, message, errorCode, custom) : nil;
- dispatch_async(dispatch_get_main_queue(), ^{
- if (!self.errorHandler || !error) {
- return;
- }
- self.errorHandler(error, session);
- });
- }
- - (NSArray<RLMSyncUser *> *)_allUsers {
- NSMutableArray<RLMSyncUser *> *buffer = [NSMutableArray array];
- for (auto user : SyncManager::shared().all_logged_in_users()) {
- [buffer addObject:[[RLMSyncUser alloc] initWithSyncUser:std::move(user)]];
- }
- return buffer;
- }
- + (void)resetForTesting {
- SyncManager::shared().reset_for_testing();
- }
- - (RLMNetworkRequestOptions *)networkRequestOptions {
- RLMNetworkRequestOptions *options = [[RLMNetworkRequestOptions alloc] init];
- options.authorizationHeaderName = self.authorizationHeaderName;
- options.customHeaders = self.customRequestHeaders;
- options.pinnedCertificatePaths = self.pinnedCertificatePaths;
- return options;
- }
- @end
|