1 2#import "EXBuildConstants.h" 3#import "EXHomeAppManager.h" 4#import "EXKernel.h" 5#import "EXAppFetcher.h" 6#import "EXAbstractLoader.h" 7#import "EXKernelLinkingManager.h" 8#import "EXHomeModule.h" 9#import "EXKernelUtil.h" 10#import "EXLog.h" 11#import "ExpoKit.h" 12#import "EXReactAppExceptionHandler.h" 13#import "EXReactAppManager+Private.h" 14#import "EXVersionManagerObjC.h" 15#import "EXVersions.h" 16#import "EXEmbeddedHomeLoader.h" 17 18#import <EXConstants/EXConstantsService.h> 19 20#import <React/RCTUtils.h> 21#import <React/RCTBridge.h> 22 23#if defined(EX_DETACHED) 24#import "ExpoKit-Swift.h" 25#else 26#import "Expo_Go-Swift.h" 27#endif // defined(EX_DETACHED) 28 29#import <ExpoModulesCore/EXModuleRegistryProvider.h> 30 31@import EXManifests; 32@import EXUpdates; 33 34NSString * const kEXHomeLaunchUrlDefaultsKey = @"EXKernelLaunchUrlDefaultsKey"; 35 36@implementation EXHomeAppManager 37 38- (NSDictionary *)extraParams 39{ 40 NSMutableDictionary *params = [@{ 41 @"browserModuleClass": [EXHomeModule class], 42 @"constants": @{ 43 @"expoRuntimeVersion": [EXBuildConstants sharedInstance].expoRuntimeVersion, 44 @"linkingUri": @"exp://", 45 @"experienceUrl": [@"exp://" stringByAppendingString:(self.appRecord.appLoader.manifest.hostUri ?: @"")], 46 @"manifest": self.appRecord.appLoader.manifest.rawManifestJSON, 47 @"executionEnvironment": EXConstantsExecutionEnvironmentStoreClient, 48 @"appOwnership": @"expo", 49 @"supportedExpoSdks": [EXVersions sharedInstance].versions[@"sdkVersions"], 50 }, 51 @"exceptionsManagerDelegate": self.exceptionHandler, 52 @"isDeveloper": @([EXBuildConstants sharedInstance].isDevKernel), 53 @"isStandardDevMenuAllowed": @(YES), // kernel enables traditional RN dev menu 54 @"manifest": self.appRecord.appLoader.manifest.rawManifestJSON, 55 @"services": [EXKernel sharedInstance].serviceRegistry.allServices, 56 @"singletonModules": [EXModuleRegistryProvider singletonModules], 57 @"fileSystemDirectories": @{ 58 @"documentDirectory": [self scopedDocumentDirectory], 59 @"cachesDirectory": [self scopedCachesDirectory] 60 } 61 } mutableCopy]; 62 63 NSURL *initialHomeUrl = [self _initialHomeUrl]; 64 if (initialHomeUrl) { 65 params[@"initialUri"] = initialHomeUrl; 66 } 67 return params; 68} 69 70#pragma mark - interfacing with home JS 71 72- (void)addHistoryItemWithUrl:(NSURL *)manifestUrl manifest:(EXManifestsManifest *)manifest 73{ 74 if (!manifest || !manifestUrl || [manifest.legacyId isEqualToString:@"@exponent/home"]) { 75 return; 76 } 77 NSDictionary *params = @{ 78 @"manifestUrl": manifestUrl.absoluteString, 79 @"manifest": manifest.rawManifestJSON, 80 }; 81 [self _dispatchHomeJSEvent:@"addHistoryItem" body:params onSuccess:nil onFailure:nil]; 82} 83 84- (void)getHistoryUrlForScopeKey:(NSString *)scopeKey completion:(void (^)(NSString *))completion 85{ 86 [self _dispatchHomeJSEvent:@"getHistoryUrlForExperienceId" 87 body:@{ @"experienceId": scopeKey } 88 onSuccess:^(NSDictionary *result) { 89 NSString *url = result[@"url"]; 90 completion(url); 91 } onFailure:^(NSString *errorMessage) { 92 completion(nil); 93 }]; 94} 95 96- (void)showQRReader 97{ 98 [self _dispatchHomeJSEvent:@"showQRReader" body:@{} onSuccess:nil onFailure:nil]; 99} 100 101#pragma mark - EXReactAppManager 102 103- (NSArray *)extraModulesForBridge:(RCTBridge *)bridge 104{ 105 NSMutableArray *modules = [NSMutableArray array]; 106 107 [modules addObjectsFromArray:[self.versionManager extraModulesForBridge:bridge]]; 108 109 return modules; 110} 111 112- (void)computeVersionSymbolPrefix 113{ 114 self.validatedVersion = nil; 115 self.versionSymbolPrefix = [[EXVersions sharedInstance] symbolPrefixForSdkVersion:self.validatedVersion isKernel:YES]; 116} 117 118- (RCTLogFunction)logFunction 119{ 120 return EXGetKernelRCTLogFunction(); 121} 122 123- (RCTLogLevel)logLevel 124{ 125 return RCTLogLevelWarning; 126} 127 128- (NSDictionary *)launchOptionsForBridge 129{ 130 if (!self.hasBridgeEverLoaded) { 131 return [ExpoKit sharedInstance].launchOptions; 132 } else { 133 // don't want to re-consume launch options when the bridge reloads. 134 return nil; 135 } 136} 137 138- (NSString *)bundleResourceNameForAppFetcher:(__unused EXAppFetcher *)appFetcher withManifest:(nonnull __unused EXManifestsManifest *)manifest 139{ 140 return kEXHomeBundleResourceName; 141} 142 143#pragma mark - util 144 145- (void)_dispatchHomeJSEvent:(NSString *)eventName body:(NSDictionary *)eventBody onSuccess:(void (^_Nullable)(NSDictionary * _Nullable))success onFailure:(void (^_Nullable)(NSString * _Nullable))failure 146{ 147 EXHomeModule *homeModule = [[EXKernel sharedInstance] nativeModuleForAppManager:self named:@"ExponentKernel"]; 148 if (homeModule) { 149 [homeModule dispatchJSEvent:eventName body:eventBody onSuccess:success onFailure:failure]; 150 } else { 151 if (failure) { 152 failure(nil); 153 } 154 } 155} 156 157- (NSURL *)_initialHomeUrl 158{ 159 // used by appetize - override the kernel initial url if there's something in NSUserDefaults 160 NSURL *initialHomeUrl; 161 NSString *kernelInitialUrlDefaultsValue = [[NSUserDefaults standardUserDefaults] stringForKey:kEXHomeLaunchUrlDefaultsKey]; 162 if (kernelInitialUrlDefaultsValue) { 163 initialHomeUrl = [NSURL URLWithString:kernelInitialUrlDefaultsValue]; 164 [[NSUserDefaults standardUserDefaults] removeObjectForKey:kEXHomeLaunchUrlDefaultsKey]; 165 [[NSUserDefaults standardUserDefaults] synchronize]; 166 } else { 167 initialHomeUrl = [EXKernelLinkingManager initialUrlFromLaunchOptions:[self launchOptionsForBridge]]; 168 } 169 return initialHomeUrl; 170} 171 172- (BOOL)requiresValidManifests 173{ 174 // running home 175 return NO; 176} 177 178@end 179