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