From 2dd40e3abba3d3a5a949aa4980f741ae412147ba Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Mon, 9 Apr 2018 14:21:00 -0700 Subject: Removing FirebaseStorage.downloadURL --- Firebase/Storage/FIRStorageErrors.m | 11 ++ Firebase/Storage/FIRStorageGetDownloadURLTask.m | 113 +++++++++++++++++++++ Firebase/Storage/FIRStorageGetMetadataTask.m | 34 ++----- Firebase/Storage/FIRStorageMetadata.m | 48 --------- Firebase/Storage/FIRStorageReference.m | 16 ++- Firebase/Storage/FIRStorageUpdateMetadataTask.m | 34 ++----- Firebase/Storage/FIRStorageUploadTask.m | 9 +- .../Storage/Private/FIRStorageConstants_Private.h | 1 - Firebase/Storage/Private/FIRStorageErrors.h | 10 +- .../Storage/Private/FIRStorageGetDownloadURLTask.h | 37 +++++++ Firebase/Storage/Public/FIRStorageMetadata.h | 14 --- 11 files changed, 197 insertions(+), 130 deletions(-) create mode 100644 Firebase/Storage/FIRStorageGetDownloadURLTask.m create mode 100644 Firebase/Storage/Private/FIRStorageGetDownloadURLTask.h (limited to 'Firebase/Storage') diff --git a/Firebase/Storage/FIRStorageErrors.m b/Firebase/Storage/FIRStorageErrors.m index ecfae02..7cc4beb 100644 --- a/Firebase/Storage/FIRStorageErrors.m +++ b/Firebase/Storage/FIRStorageErrors.m @@ -170,4 +170,15 @@ return clientError; } ++ (NSError *)errorWithInvalidRequest:(NSData *)request { + NSString *requestString = [[NSString alloc] initWithData:request encoding:NSUTF8StringEncoding]; + NSString *invalidDataString = + [NSString stringWithFormat:kFIRStorageInvalidDataFormat, requestString]; + NSDictionary *dict; + if (invalidDataString.length > 0) { + dict = @{NSLocalizedFailureReasonErrorKey : invalidDataString}; + } + return [FIRStorageErrors errorWithCode:FIRStorageErrorCodeUnknown infoDictionary:dict]; +} + @end diff --git a/Firebase/Storage/FIRStorageGetDownloadURLTask.m b/Firebase/Storage/FIRStorageGetDownloadURLTask.m new file mode 100644 index 0000000..c46bbd8 --- /dev/null +++ b/Firebase/Storage/FIRStorageGetDownloadURLTask.m @@ -0,0 +1,113 @@ +// Copyright 2018 Google +// +// 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 "FIRStorageGetDownloadURLTask.h" +#import + +#import "FIRStorageConstants.h" +#import "FIRStorageMetadata_Private.h" +#import "FIRStorageTask_Private.h" +#import "FIRStorageUtils.h" + +#import "FirebaseStorage.h" + +@implementation FIRStorageGetDownloadURLTask { + @private + FIRStorageVoidURLError _completion; +} + +@synthesize fetcher = _fetcher; +@synthesize fetcherCompletion = _fetcherCompletion; + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + completion:(FIRStorageVoidURLError)completion { + self = [super initWithReference:reference fetcherService:service]; + if (self) { + _completion = [completion copy]; + } + return self; +} + +- (void)dealloc { + [_fetcher stopFetching]; +} + ++ (NSURL *)downloadURLFromMetadataDictionary:(NSDictionary *)dictionary { + NSString *downloadTokens = dictionary[kFIRStorageMetadataDownloadTokens]; + + if (downloadTokens && downloadTokens.length > 0) { + NSArray *downloadTokenArray = [downloadTokens componentsSeparatedByString:@","]; + NSString *bucket = dictionary[kFIRStorageMetadataBucket]; + NSString *path = dictionary[kFIRStorageMetadataName]; + NSString *fullPath = [NSString stringWithFormat:kFIRStorageFullPathFormat, bucket, + [FIRStorageUtils GCSEscapedString:path]]; + + NSURLComponents *components = [[NSURLComponents alloc] init]; + components.scheme = kFIRStorageScheme; + components.host = kFIRStorageHost; + components.percentEncodedPath = fullPath; + components.query = [NSString stringWithFormat:@"alt=media&token=%@", downloadTokenArray[0]]; + + return [components URL]; + } + + return nil; +} + +- (void)enqueue { + NSMutableURLRequest *request = [self.baseRequest mutableCopy]; + request.HTTPMethod = @"GET"; + request.timeoutInterval = self.reference.storage.maxDownloadRetryTime; + + FIRStorageVoidURLError callback = _completion; + _completion = nil; + + GTMSessionFetcher *fetcher = [self.fetcherService fetcherWithRequest:request]; + _fetcher = fetcher; + fetcher.comment = @"DownloadURLTask"; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + _fetcherCompletion = ^(NSData *data, NSError *error) { + NSURL *downloadURL; + if (error) { + if (!self.error) { + self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; + } + } else { + NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data]; + if (responseDictionary != nil) { + downloadURL = + [FIRStorageGetDownloadURLTask downloadURLFromMetadataDictionary:responseDictionary]; + } else { + self.error = [FIRStorageErrors errorWithInvalidRequest:data]; + } + } + + if (callback) { + callback(downloadURL, self.error); + } + + self->_fetcherCompletion = nil; + }; +#pragma clang diagnostic pop + + __weak FIRStorageGetDownloadURLTask *weakSelf = self; + [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + weakSelf.fetcherCompletion(data, error); + }]; +} + +@end diff --git a/Firebase/Storage/FIRStorageGetMetadataTask.m b/Firebase/Storage/FIRStorageGetMetadataTask.m index 2623652..077dcd7 100644 --- a/Firebase/Storage/FIRStorageGetMetadataTask.m +++ b/Firebase/Storage/FIRStorageGetMetadataTask.m @@ -58,37 +58,23 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-retain-cycles" _fetcherCompletion = ^(NSData *data, NSError *error) { + FIRStorageMetadata *metadata; if (error) { if (!self.error) { self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; } - if (callback) { - callback(nil, self.error); + } else { + NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data]; + if (responseDictionary != nil) { + metadata = [[FIRStorageMetadata alloc] initWithDictionary:responseDictionary]; + [metadata setType:FIRStorageMetadataTypeFile]; + } else { + self.error = [FIRStorageErrors errorWithInvalidRequest:data]; } - self->_fetcherCompletion = nil; - return; } - NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data]; - if (responseDictionary != nil) { - FIRStorageMetadata *metadata = - [[FIRStorageMetadata alloc] initWithDictionary:responseDictionary]; - [metadata setType:FIRStorageMetadataTypeFile]; - if (callback) { - callback(metadata, nil); - } - } else { - NSString *returnedData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - NSString *invalidDataString = - [NSString stringWithFormat:kFIRStorageInvalidDataFormat, returnedData]; - NSDictionary *dict; - if (invalidDataString.length > 0) { - dict = @{NSLocalizedFailureReasonErrorKey : invalidDataString}; - } - self.error = [FIRStorageErrors errorWithCode:FIRStorageErrorCodeUnknown infoDictionary:dict]; - if (callback) { - callback(nil, self.error); - } + if (callback) { + callback(metadata, self.error); } self->_fetcherCompletion = nil; }; diff --git a/Firebase/Storage/FIRStorageMetadata.m b/Firebase/Storage/FIRStorageMetadata.m index ab25076..764907c 100644 --- a/Firebase/Storage/FIRStorageMetadata.m +++ b/Firebase/Storage/FIRStorageMetadata.m @@ -41,7 +41,6 @@ _contentType = dictionary[kFIRStorageMetadataContentType]; _customMetadata = dictionary[kFIRStorageMetadataCustomMetadata]; _size = [dictionary[kFIRStorageMetadataSize] longLongValue]; - _downloadURLs = dictionary[kFIRStorageMetadataDownloadURLs]; _generation = [dictionary[kFIRStorageMetadataGeneration] longLongValue]; _metageneration = [dictionary[kFIRStorageMetadataMetageneration] longLongValue]; _timeCreated = [self dateFromRFC3339String:dictionary[kFIRStorageMetadataTimeCreated]]; @@ -50,26 +49,6 @@ // GCS "name" is our path, our "name" is just the last path component of the path _path = dictionary[kFIRStorageMetadataName]; _name = [_path lastPathComponent]; - NSString *downloadTokens = dictionary[kFIRStorageMetadataDownloadTokens]; - if (downloadTokens) { - NSArray *downloadStringArray = [downloadTokens componentsSeparatedByString:@","]; - NSMutableArray *downloadURLArray = - [[NSMutableArray alloc] initWithCapacity:[downloadStringArray count]]; - [downloadStringArray enumerateObjectsUsingBlock:^(NSString *_Nonnull token, NSUInteger idx, - BOOL *_Nonnull stop) { - NSURLComponents *components = [[NSURLComponents alloc] init]; - components.scheme = kFIRStorageScheme; - components.host = kFIRStorageHost; - NSString *path = [FIRStorageUtils GCSEscapedString:self->_path]; - NSString *fullPath = - [NSString stringWithFormat:kFIRStorageFullPathFormat, self->_bucket, path]; - components.percentEncodedPath = fullPath; - components.query = [NSString stringWithFormat:@"alt=media&token=%@", token]; - - [downloadURLArray insertObject:[components URL] atIndex:idx]; - }]; - _downloadURLs = downloadURLArray; - } } return self; } @@ -147,29 +126,6 @@ metadataDictionary[kFIRStorageMetadataCustomMetadata] = _customMetadata; } - if (_downloadURLs) { - NSMutableArray *downloadTokens = [[NSMutableArray alloc] init]; - [_downloadURLs - enumerateObjectsUsingBlock:^(NSURL *_Nonnull URL, NSUInteger idx, BOOL *_Nonnull stop) { - NSArray *queryItems = [URL.query componentsSeparatedByString:@"&"]; - [queryItems enumerateObjectsUsingBlock:^(NSString *queryString, NSUInteger idx, - BOOL *_Nonnull stop) { - NSString *key; - NSString *value; - NSScanner *scanner = [NSScanner scannerWithString:queryString]; - [scanner scanUpToString:@"=" intoString:&key]; - [scanner scanString:@"=" intoString:NULL]; - [scanner scanUpToString:@"\n" intoString:&value]; - if ([key isEqual:@"token"]) { - [downloadTokens addObject:value]; - *stop = YES; - } - }]; - }]; - NSString *downloadTokenString = [downloadTokens componentsJoinedByString:@","]; - metadataDictionary[kFIRStorageMetadataDownloadTokens] = downloadTokenString; - } - if (_generation) { NSString *generationString = [NSString stringWithFormat:@"%lld", _generation]; metadataDictionary[kFIRStorageMetadataGeneration] = generationString; @@ -207,10 +163,6 @@ return _type == FIRStorageMetadataTypeFolder; } -- (nullable NSURL *)downloadURL { - return [_downloadURLs firstObject]; -} - #pragma mark - Private methods + (void)removeMatchingMetadata:(NSMutableDictionary *)metadata diff --git a/Firebase/Storage/FIRStorageReference.m b/Firebase/Storage/FIRStorageReference.m index 7bc1934..5b70a9c 100644 --- a/Firebase/Storage/FIRStorageReference.m +++ b/Firebase/Storage/FIRStorageReference.m @@ -17,6 +17,7 @@ #import "FIRStorageConstants_Private.h" #import "FIRStorageDeleteTask.h" #import "FIRStorageDownloadTask_Private.h" +#import "FIRStorageGetDownloadURLTask.h" #import "FIRStorageGetMetadataTask.h" #import "FIRStorageMetadata_Private.h" #import "FIRStorageReference_Private.h" @@ -319,16 +320,11 @@ } - (void)downloadURLWithCompletion:(FIRStorageVoidURLError)completion { - dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue; - if (!callbackQueue) { - callbackQueue = dispatch_get_main_queue(); - } - - return [self metadataWithCompletion:^(FIRStorageMetadata *metadata, NSError *error) { - dispatch_async(callbackQueue, ^{ - completion(metadata.downloadURL, error); - }); - }]; + FIRStorageGetDownloadURLTask *task = + [[FIRStorageGetDownloadURLTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + completion:completion]; + [task enqueue]; } #pragma mark - Metadata Operations diff --git a/Firebase/Storage/FIRStorageUpdateMetadataTask.m b/Firebase/Storage/FIRStorageUpdateMetadataTask.m index fa5955a..d866329 100644 --- a/Firebase/Storage/FIRStorageUpdateMetadataTask.m +++ b/Firebase/Storage/FIRStorageUpdateMetadataTask.m @@ -64,37 +64,23 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-retain-cycles" _fetcherCompletion = ^(NSData *data, NSError *error) { + FIRStorageMetadata *metadata; if (error) { if (!self.error) { self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; } - if (callback) { - callback(nil, self.error); + } else { + NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data]; + if (responseDictionary) { + metadata = [[FIRStorageMetadata alloc] initWithDictionary:responseDictionary]; + [metadata setType:FIRStorageMetadataTypeFile]; + } else { + self.error = [FIRStorageErrors errorWithInvalidRequest:data]; } - self->_fetcherCompletion = nil; - return; } - NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data]; - if (responseDictionary) { - FIRStorageMetadata *metadata = - [[FIRStorageMetadata alloc] initWithDictionary:responseDictionary]; - [metadata setType:FIRStorageMetadataTypeFile]; - if (callback) { - callback(metadata, nil); - } - } else { - NSString *returnedData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - NSString *invalidDataString = - [NSString stringWithFormat:kFIRStorageInvalidDataFormat, returnedData]; - NSDictionary *dict; - if (invalidDataString.length > 0) { - dict = @{NSLocalizedFailureReasonErrorKey : invalidDataString}; - } - self.error = [FIRStorageErrors errorWithCode:FIRStorageErrorCodeUnknown infoDictionary:dict]; - if (callback) { - callback(nil, self.error); - } + if (callback) { + callback(metadata, self.error); } self->_fetcherCompletion = nil; }; diff --git a/Firebase/Storage/FIRStorageUploadTask.m b/Firebase/Storage/FIRStorageUploadTask.m index f84c2c7..2c4daa9 100644 --- a/Firebase/Storage/FIRStorageUploadTask.m +++ b/Firebase/Storage/FIRStorageUploadTask.m @@ -154,14 +154,7 @@ [metadata setType:FIRStorageMetadataTypeFile]; self.metadata = metadata; } else { - NSString *returnedData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - NSString *invalidDataString = - [NSString stringWithFormat:kFIRStorageInvalidDataFormat, returnedData]; - NSDictionary *dict; - if (invalidDataString.length > 0) { - dict = @{NSLocalizedFailureReasonErrorKey : invalidDataString}; - } - self.error = [FIRStorageErrors errorWithCode:FIRStorageErrorCodeUnknown infoDictionary:dict]; + self.error = [FIRStorageErrors errorWithInvalidRequest:data]; } [self fireHandlersForStatus:FIRStorageTaskStatusSuccess snapshot:self.snapshot]; diff --git a/Firebase/Storage/Private/FIRStorageConstants_Private.h b/Firebase/Storage/Private/FIRStorageConstants_Private.h index 498c687..cf12337 100644 --- a/Firebase/Storage/Private/FIRStorageConstants_Private.h +++ b/Firebase/Storage/Private/FIRStorageConstants_Private.h @@ -55,7 +55,6 @@ FOUNDATION_EXPORT NSString *const kFIRStorageMetadataContentLanguage; FOUNDATION_EXPORT NSString *const kFIRStorageMetadataContentType; FOUNDATION_EXPORT NSString *const kFIRStorageMetadataCustomMetadata; FOUNDATION_EXPORT NSString *const kFIRStorageMetadataSize; -FOUNDATION_EXPORT NSString *const kFIRStorageMetadataDownloadURLs; FOUNDATION_EXPORT NSString *const kFIRStorageMetadataGeneration; FOUNDATION_EXPORT NSString *const kFIRStorageMetadataMetageneration; FOUNDATION_EXPORT NSString *const kFIRStorageMetadataTimeCreated; diff --git a/Firebase/Storage/Private/FIRStorageErrors.h b/Firebase/Storage/Private/FIRStorageErrors.h index 7c236d9..46e87d2 100644 --- a/Firebase/Storage/Private/FIRStorageErrors.h +++ b/Firebase/Storage/Private/FIRStorageErrors.h @@ -44,11 +44,19 @@ NS_ASSUME_NONNULL_BEGIN * Creates a Firebase Storage error from a specific GCS error and FIRStorageReference. * @param error Server error to wrap and return as a Firebase Storage error. * @param reference FIRStorageReference which provides context about the request being made. - * @return Returns an Firebase Storage error, or nil if no error is provided. + * @return Returns a Firebase Storage error, or nil if no error is provided. */ + (nullable NSError *)errorWithServerError:(nullable NSError *)error reference:(nullable FIRStorageReference *)reference; +/** + * Creates a Firebase Storage error from an invalid request. + * + * @param request The NSData representation of the invalid user request. + * @return Returns the corresponding Firebase Storage error. + */ ++ (NSError *)errorWithInvalidRequest:(NSData *)request; + @end NS_ASSUME_NONNULL_END diff --git a/Firebase/Storage/Private/FIRStorageGetDownloadURLTask.h b/Firebase/Storage/Private/FIRStorageGetDownloadURLTask.h new file mode 100644 index 0000000..c349f30 --- /dev/null +++ b/Firebase/Storage/Private/FIRStorageGetDownloadURLTask.h @@ -0,0 +1,37 @@ +/* + * Copyright 2018 Google + * + * 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 "FIRStorageTask.h" + +@class GTMSessionFetcherService; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Task which provides the ability to get a download URL for an object in Firebase Storage. + */ +@interface FIRStorageGetDownloadURLTask : FIRStorageTask + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + completion:(FIRStorageVoidURLError)completion; + +// Visible for testing. ++ (NSURL *)downloadURLFromMetadataDictionary:(NSDictionary *)dictionary; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Firebase/Storage/Public/FIRStorageMetadata.h b/Firebase/Storage/Public/FIRStorageMetadata.h index 2e3cc13..63b8798 100644 --- a/Firebase/Storage/Public/FIRStorageMetadata.h +++ b/Firebase/Storage/Public/FIRStorageMetadata.h @@ -112,12 +112,6 @@ NS_SWIFT_NAME(StorageMetadata) */ @property(strong, nonatomic, readonly, nullable) FIRStorageReference *storageReference; -/** - * An array containing all download URLs available for the object. - */ -@property(strong, nonatomic, readonly, nullable) NSArray *downloadURLs __deprecated_msg( - "Use `StorageReference.downloadURLWithCompletion()` to obtain a current download URL."); - /** * Creates an instanece of FIRStorageMetadata from the contents of a dictionary. * @return An instance of FIRStorageMetadata that represents the contents of a dictionary. @@ -141,14 +135,6 @@ NS_SWIFT_NAME(StorageMetadata) */ @property(readonly, getter=isFolder) BOOL folder; -/** - * Retrieves a download URL for the given object, or nil if none exist. - * Note that if there are many valid download tokens, this will always return the first - * valid token created. - */ -- (nullable NSURL *)downloadURL __deprecated_msg( - "Use `StorageReference.downloadURLWithCompletion()` to obtain a current download URL."); - @end NS_ASSUME_NONNULL_END -- cgit v1.2.3