1// Copyright 2015-present 650 Industries. All rights reserved. 2 3#import "EXApiUtil.h" 4#import "EXAppFetcher+Private.h" 5#import "EXAbstractLoader.h" 6#import "EXEnvironment.h" 7#import "EXErrorRecoveryManager.h" 8#import "EXJavaScriptResource.h" 9#import "EXKernel.h" 10#import "EXVersions.h" 11 12#import <React/RCTUtils.h> 13 14@import EXManifests; 15 16NS_ASSUME_NONNULL_BEGIN 17 18@implementation EXAppFetcher 19 20- (instancetype)initWithAppLoader:(EXAbstractLoader *)appLoader 21{ 22 if (self = [super init]) { 23 _appLoader = appLoader; 24 } 25 return self; 26} 27 28- (void)start 29{ 30 // overridden by subclasses 31 @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Should not call EXAppFetcher#start -- use a subclass instead" userInfo:nil]; 32} 33 34- (void)fetchJSBundleWithManifest:(EXManifestsManifest *)manifest 35 cacheBehavior:(EXCachedResourceBehavior)cacheBehavior 36 timeoutInterval:(NSTimeInterval)timeoutInterval 37 progress:(void (^ _Nullable )(EXLoadingProgress *))progressBlock 38 success:(void (^)(NSData *))successBlock 39 error:(void (^)(NSError *))errorBlock 40{ 41 EXJavaScriptResource *jsResource = [[EXJavaScriptResource alloc] initWithBundleName:[self.dataSource bundleResourceNameForAppFetcher:self withManifest:manifest] 42 remoteUrl:[EXApiUtil bundleUrlFromManifest:manifest] 43 devToolsEnabled:manifest.isUsingDeveloperTool]; 44 jsResource.abiVersion = [[EXVersions sharedInstance] availableSdkVersionForManifest:manifest]; 45 jsResource.requestTimeoutInterval = timeoutInterval; 46 47 EXCachedResourceBehavior behavior = cacheBehavior; 48 // if we've disabled updates, ignore all other settings and only use the cache 49 if ([EXEnvironment sharedEnvironment].isDetached && ![EXEnvironment sharedEnvironment].areRemoteUpdatesEnabled) { 50 behavior = EXCachedResourceOnlyCache; 51 } 52 53 if ([self.dataSource appFetcherShouldInvalidateBundleCache:self]) { 54 [jsResource removeCache]; 55 } 56 57 [jsResource loadResourceWithBehavior:cacheBehavior progressBlock:progressBlock successBlock:successBlock errorBlock:errorBlock]; 58} 59 60+ (EXCachedResourceBehavior)cacheBehaviorForJSWithManifest:(EXManifestsManifest * _Nonnull)manifest 61{ 62 if ([[EXKernel sharedInstance].serviceRegistry.errorRecoveryManager scopeKeyIsRecoveringFromError:manifest.scopeKey]) { 63 // if this experience id encountered a loading error before, discard any cache we might have 64 return EXCachedResourceWriteToCache; 65 } 66 if (manifest.isUsingDeveloperTool) { 67 return EXCachedResourceNoCache; 68 } 69 return EXCachedResourceWriteToCache; 70} 71 72@end 73 74NS_ASSUME_NONNULL_END 75 76