From 1ff34ab5e66fc20a08c9ad762e122815301f7270 Mon Sep 17 00:00:00 2001 From: Richard Zito Date: Thu, 31 Jan 2019 04:49:33 -0800 Subject: [PATCH] Revert D13895627: [react-native][PR] [iOS] Enhance image freshness check before stored into cache Differential Revision: D13895627 Original commit changeset: aa377511c31b fbshipit-source-id: 7785644d48d750fb75b2d7652a4b68da27c5fc3f --- Libraries/Image/RCTImageCache.m | 60 ++++++++++++-------------------- Libraries/Image/RCTImageLoader.h | 3 +- Libraries/Image/RCTImageLoader.m | 40 ++++++++++++--------- 3 files changed, 47 insertions(+), 56 deletions(-) diff --git a/Libraries/Image/RCTImageCache.m b/Libraries/Image/RCTImageCache.m index a6546a7e26ce17..9a941f1b889e1a 100644 --- a/Libraries/Image/RCTImageCache.m +++ b/Libraries/Image/RCTImageCache.m @@ -106,49 +106,33 @@ - (void)addImageToCache:(UIImage *)image size:(CGSize)size scale:(CGFloat)scale resizeMode:(RCTResizeMode)resizeMode - response:(NSURLResponse *)response + responseDate:(NSString *)responseDate + cacheControl:(NSString *)cacheControl { - if ([response isKindOfClass:[NSHTTPURLResponse class]]) { - NSString *cacheKey = RCTCacheKeyForImage(url, size, scale, resizeMode); - BOOL shouldCache = YES; - NSString *responseDate = ((NSHTTPURLResponse *)response).allHeaderFields[@"Date"]; - NSDate *originalDate = [self dateWithHeaderString:responseDate]; - NSString *cacheControl = ((NSHTTPURLResponse *)response).allHeaderFields[@"Cache-Control"]; - NSDate *staleTime; - NSArray *components = [cacheControl componentsSeparatedByString:@","]; - for (NSString *component in components) { - if ([component containsString:@"no-cache"] || [component containsString:@"no-store"] || [component hasSuffix:@"max-age=0"]) { - shouldCache = NO; - break; - } else { - NSRange range = [component rangeOfString:@"max-age="]; - if (range.location != NSNotFound) { - NSInteger seconds = [[component substringFromIndex:range.location + range.length] integerValue]; - staleTime = [originalDate dateByAddingTimeInterval:(NSTimeInterval)seconds]; - } + NSString *cacheKey = RCTCacheKeyForImage(url, size, scale, resizeMode); + BOOL shouldCache = YES; + NSDate *staleTime; + NSArray *components = [cacheControl componentsSeparatedByString:@","]; + for (NSString *component in components) { + if ([component containsString:@"no-cache"] || [component containsString:@"no-store"] || [component hasSuffix:@"max-age=0"]) { + shouldCache = NO; + break; + } else { + NSRange range = [component rangeOfString:@"max-age="]; + if (range.location != NSNotFound) { + NSInteger seconds = [[component substringFromIndex:range.location + range.length] integerValue]; + NSDate *originalDate = [self dateWithHeaderString:responseDate]; + staleTime = [originalDate dateByAddingTimeInterval:(NSTimeInterval)seconds]; } } - if (shouldCache) { - if (!staleTime && originalDate) { - NSString *expires = ((NSHTTPURLResponse *)response).allHeaderFields[@"Expires"]; - NSString *lastModified = ((NSHTTPURLResponse *)response).allHeaderFields[@"Last-Modified"]; - if (expires) { - staleTime = [self dateWithHeaderString:expires]; - } else if (lastModified) { - NSDate *lastModifiedDate = [self dateWithHeaderString:lastModified]; - if (lastModifiedDate) { - NSTimeInterval interval = [originalDate timeIntervalSinceDate:lastModifiedDate] / 10; - staleTime = [originalDate dateByAddingTimeInterval:interval]; - } - } - } - if (staleTime) { - @synchronized(_cacheStaleTimes) { - _cacheStaleTimes[cacheKey] = staleTime; - } + } + if (shouldCache) { + if (staleTime) { + @synchronized(_cacheStaleTimes) { + _cacheStaleTimes[cacheKey] = staleTime; } - return [self addImageToCache:image forKey:cacheKey]; } + return [self addImageToCache:image forKey:cacheKey]; } } diff --git a/Libraries/Image/RCTImageLoader.h b/Libraries/Image/RCTImageLoader.h index da4e04ced955d6..0d611b1b5164dd 100644 --- a/Libraries/Image/RCTImageLoader.h +++ b/Libraries/Image/RCTImageLoader.h @@ -31,7 +31,8 @@ typedef dispatch_block_t RCTImageLoaderCancellationBlock; size:(CGSize)size scale:(CGFloat)scale resizeMode:(RCTResizeMode)resizeMode - response:(NSURLResponse *)response; + responseDate:(NSString *)responseDate + cacheControl:(NSString *)cacheControl; @end diff --git a/Libraries/Image/RCTImageLoader.m b/Libraries/Image/RCTImageLoader.m index b9276f00f86eaf..bb04437a997ee6 100644 --- a/Libraries/Image/RCTImageLoader.m +++ b/Libraries/Image/RCTImageLoader.m @@ -346,7 +346,7 @@ - (RCTImageLoaderCancellationBlock)_loadImageOrDataWithURLRequest:(NSURLRequest resizeMode:(RCTResizeMode)resizeMode progressBlock:(RCTImageLoaderProgressBlock)progressHandler partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadHandler - completionBlock:(void (^)(NSError *error, id imageOrData, BOOL cacheResult, NSURLResponse *response))completionBlock + completionBlock:(void (^)(NSError *error, id imageOrData, BOOL cacheResult, NSString *fetchDate, NSString *cacheControl))completionBlock { { NSMutableURLRequest *mutableRequest = [request mutableCopy]; @@ -375,7 +375,7 @@ - (RCTImageLoaderCancellationBlock)_loadImageOrDataWithURLRequest:(NSURLRequest __block atomic_bool cancelled = ATOMIC_VAR_INIT(NO); // TODO: Protect this variable shared between threads. __block dispatch_block_t cancelLoad = nil; - void (^completionHandler)(NSError *, id, NSURLResponse *) = ^(NSError *error, id imageOrData, NSURLResponse *response) { + void (^completionHandler)(NSError *, id, NSString *, NSString *) = ^(NSError *error, id imageOrData, NSString *fetchDate, NSString *cacheControl) { cancelLoad = nil; // If we've received an image, we should try to set it synchronously, @@ -385,11 +385,11 @@ - (RCTImageLoaderCancellationBlock)_loadImageOrDataWithURLRequest:(NSURLRequest // expecting it, and may do expensive post-processing in the callback dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ if (!atomic_load(&cancelled)) { - completionBlock(error, imageOrData, cacheResult, response); + completionBlock(error, imageOrData, cacheResult, fetchDate, cacheControl); } }); } else if (!atomic_load(&cancelled)) { - completionBlock(error, imageOrData, cacheResult, response); + completionBlock(error, imageOrData, cacheResult, fetchDate, cacheControl); } }; @@ -403,7 +403,7 @@ - (RCTImageLoaderCancellationBlock)_loadImageOrDataWithURLRequest:(NSURLRequest progressHandler:progressHandler partialLoadHandler:partialLoadHandler completionHandler:^(NSError *error, UIImage *image){ - completionHandler(error, image, nil); + completionHandler(error, image, nil, nil); }]; } @@ -427,7 +427,7 @@ - (RCTImageLoaderCancellationBlock)_loadImageOrDataWithURLRequest:(NSURLRequest progressHandler:progressHandler partialLoadHandler:partialLoadHandler completionHandler:^(NSError *error, UIImage *image) { - completionHandler(error, image, nil); + completionHandler(error, image, nil, nil); }]; } else { UIImage *image; @@ -439,7 +439,7 @@ - (RCTImageLoaderCancellationBlock)_loadImageOrDataWithURLRequest:(NSURLRequest } if (image) { - completionHandler(nil, image, nil); + completionHandler(nil, image, nil, nil); } else { // Use networking module to load image cancelLoad = [strongSelf _loadURLRequest:request @@ -464,7 +464,7 @@ - (RCTImageLoaderCancellationBlock)_loadImageOrDataWithURLRequest:(NSURLRequest - (RCTImageLoaderCancellationBlock)_loadURLRequest:(NSURLRequest *)request progressBlock:(RCTImageLoaderProgressBlock)progressHandler - completionBlock:(void (^)(NSError *error, id imageOrData, NSURLResponse *response))completionHandler + completionBlock:(void (^)(NSError *error, id imageOrData, NSString *fetchDate, NSString *cacheControl))completionHandler { // Check if networking module is available if (RCT_DEBUG && ![_bridge respondsToSelector:@selector(networking)]) { @@ -486,17 +486,19 @@ - (RCTImageLoaderCancellationBlock)_loadURLRequest:(NSURLRequest *)request RCTURLRequestCompletionBlock processResponse = ^(NSURLResponse *response, NSData *data, NSError *error) { // Check for system errors if (error) { - completionHandler(error, nil, response); + completionHandler(error, nil, nil, nil); return; } else if (!response) { - completionHandler(RCTErrorWithMessage(@"Response metadata error"), nil, response); + completionHandler(RCTErrorWithMessage(@"Response metadata error"), nil, nil, nil); return; } else if (!data) { - completionHandler(RCTErrorWithMessage(@"Unknown image download error"), nil, response); + completionHandler(RCTErrorWithMessage(@"Unknown image download error"), nil, nil, nil); return; } // Check for http errors + NSString *responseDate; + NSString *cacheControl; if ([response isKindOfClass:[NSHTTPURLResponse class]]) { NSInteger statusCode = ((NSHTTPURLResponse *)response).statusCode; if (statusCode != 200) { @@ -504,13 +506,16 @@ - (RCTImageLoaderCancellationBlock)_loadURLRequest:(NSURLRequest *)request NSDictionary *userInfo = @{NSLocalizedDescriptionKey: errorMessage}; completionHandler([[NSError alloc] initWithDomain:NSURLErrorDomain code:statusCode - userInfo:userInfo], nil, response); + userInfo:userInfo], nil, nil, nil); return; } + + responseDate = ((NSHTTPURLResponse *)response).allHeaderFields[@"Date"]; + cacheControl = ((NSHTTPURLResponse *)response).allHeaderFields[@"Cache-Control"]; } // Call handler - completionHandler(nil, data, response); + completionHandler(nil, data, responseDate, cacheControl); }; // Download image @@ -532,7 +537,7 @@ - (RCTImageLoaderCancellationBlock)_loadURLRequest:(NSURLRequest *)request } else { someError = RCTErrorWithMessage(@"Unknown image download error"); } - completionHandler(someError, nil, response); + completionHandler(someError, nil, nil, nil); [strongSelf dequeueTasks]; return; } @@ -598,7 +603,7 @@ - (RCTImageLoaderCancellationBlock)loadImageWithURLRequest:(NSURLRequest *)image }; __weak RCTImageLoader *weakSelf = self; - void (^completionHandler)(NSError *, id, BOOL, NSURLResponse *) = ^(NSError *error, id imageOrData, BOOL cacheResult, NSURLResponse *response) { + void (^completionHandler)(NSError *, id, BOOL, NSString *, NSString *) = ^(NSError *error, id imageOrData, BOOL cacheResult, NSString *fetchDate, NSString *cacheControl) { __typeof(self) strongSelf = weakSelf; if (atomic_load(&cancelled) || !strongSelf) { return; @@ -618,7 +623,8 @@ - (RCTImageLoaderCancellationBlock)loadImageWithURLRequest:(NSURLRequest *)image size:size scale:scale resizeMode:resizeMode - response:response]; + responseDate:fetchDate + cacheControl:cacheControl]; } cancelLoad = nil; @@ -752,7 +758,7 @@ - (RCTImageLoaderCancellationBlock)decodeImageData:(NSData *)data - (RCTImageLoaderCancellationBlock)getImageSizeForURLRequest:(NSURLRequest *)imageURLRequest block:(void(^)(NSError *error, CGSize size))callback { - void (^completion)(NSError *, id, BOOL, NSURLResponse *) = ^(NSError *error, id imageOrData, BOOL cacheResult, NSURLResponse *response) { + void (^completion)(NSError *, id, BOOL, NSString *, NSString *) = ^(NSError *error, id imageOrData, BOOL cacheResult, NSString *fetchDate, NSString *cacheControl) { CGSize size; if ([imageOrData isKindOfClass:[NSData class]]) { NSDictionary *meta = RCTGetImageMetadata(imageOrData);