aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firebase/Storage
diff options
context:
space:
mode:
authorGravatar Sebastian Schmidt <mrschmidt@google.com>2018-04-13 14:37:28 -0700
committerGravatar GitHub <noreply@github.com>2018-04-13 14:37:28 -0700
commit4e01558661d74cb7eba3b6ba66d3ecc90720d5f6 (patch)
treef89ca0b8bd61c01b9dd70cbced72687672f5a653 /Firebase/Storage
parent60d43d7b0980719beac21811da712f1cb4881308 (diff)
parentd7316f70dc4825e75cecd47740c0541248aa9641 (diff)
Merge pull request #1055 from firebase/mrschmidt-removedownloadurl
Removing FirebaseStorage.downloadURL
Diffstat (limited to 'Firebase/Storage')
-rw-r--r--Firebase/Storage/CHANGELOG.md6
-rw-r--r--Firebase/Storage/FIRStorageErrors.m17
-rw-r--r--Firebase/Storage/FIRStorageGetDownloadURLTask.m117
-rw-r--r--Firebase/Storage/FIRStorageGetMetadataTask.m36
-rw-r--r--Firebase/Storage/FIRStorageMetadata.m48
-rw-r--r--Firebase/Storage/FIRStorageReference.m16
-rw-r--r--Firebase/Storage/FIRStorageUpdateMetadataTask.m36
-rw-r--r--Firebase/Storage/FIRStorageUploadTask.m9
-rw-r--r--Firebase/Storage/Private/FIRStorageConstants_Private.h1
-rw-r--r--Firebase/Storage/Private/FIRStorageErrors.h18
-rw-r--r--Firebase/Storage/Private/FIRStorageGetDownloadURLTask.h34
-rw-r--r--Firebase/Storage/Private/FIRStorageGetDownloadURLTask_Private.h31
-rw-r--r--Firebase/Storage/Public/FIRStorageMetadata.h14
13 files changed, 250 insertions, 133 deletions
diff --git a/Firebase/Storage/CHANGELOG.md b/Firebase/Storage/CHANGELOG.md
index 5054cf2..135de40 100644
--- a/Firebase/Storage/CHANGELOG.md
+++ b/Firebase/Storage/CHANGELOG.md
@@ -1,5 +1,9 @@
+# v3.0.0
+- [removed] Removed `downloadURLs` property on `StorageMetadata`. Use `StorageReference.downloadURL(completion:)` to obtain a current download URL.
+- [changed] The `maxOperationRetryTime` timeout now applies to calls to `StorageReference.getMetadata(completion:)` and `StorageReference.updateMetadata(completion:)`. These calls previously used the `maxDownloadRetryTime` and `maxUploadRetryTime` timeouts.
+
# v2.2.0
-- [changed] Deprecated `downloadURLs` property on `StorageMetadata`. Use `StorageReference.downloadURLWithCompletion()` to obtain a current download URL.
+- [changed] Deprecated `downloadURLs` property on `StorageMetadata`. Use `StorageReference.downloadURL(completion:)` to obtain a current download URL.
# v2.1.3
- [changed] Addresses CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF warnings that surface in newer versions of Xcode and CocoaPods.
diff --git a/Firebase/Storage/FIRStorageErrors.m b/Firebase/Storage/FIRStorageErrors.m
index ecfae02..651bfd1 100644
--- a/Firebase/Storage/FIRStorageErrors.m
+++ b/Firebase/Storage/FIRStorageErrors.m
@@ -170,4 +170,21 @@
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];
+}
+
++ (NSError *)errorWithCustomMessage:(NSString *)errorMessage {
+ return [NSError errorWithDomain:FIRStorageErrorDomain
+ code:FIRStorageErrorCodeUnknown
+ userInfo:@{NSLocalizedDescriptionKey : errorMessage}];
+}
+
@end
diff --git a/Firebase/Storage/FIRStorageGetDownloadURLTask.m b/Firebase/Storage/FIRStorageGetDownloadURLTask.m
new file mode 100644
index 0000000..02d202e
--- /dev/null
+++ b/Firebase/Storage/FIRStorageGetDownloadURLTask.m
@@ -0,0 +1,117 @@
+// 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 "FIRStorageTask_Private.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<NSString *> *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;
+
+ // The backend can return an arbitrary number of download tokens, but we only expose the first
+ // token via the download URL.
+ NSURLQueryItem *altItem = [[NSURLQueryItem alloc] initWithName:@"alt" value:@"media"];
+ NSURLQueryItem *tokenItem =
+ [[NSURLQueryItem alloc] initWithName:@"token" value:downloadTokenArray[0]];
+ components.queryItems = @[ altItem, tokenItem ];
+
+ return [components URL];
+ }
+
+ return nil;
+}
+
+- (void)enqueue {
+ NSMutableURLRequest *request = [self.baseRequest mutableCopy];
+ request.HTTPMethod = @"GET";
+ request.timeoutInterval = self.reference.storage.maxOperationRetryTime;
+
+ FIRStorageVoidURLError callback = _completion;
+ _completion = nil;
+
+ GTMSessionFetcher *fetcher = [self.fetcherService fetcherWithRequest:request];
+ _fetcher = fetcher;
+ fetcher.comment = @"GetDownloadURLTask";
+
+#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];
+ if (!downloadURL) {
+ self.error =
+ [FIRStorageErrors errorWithCustomMessage:@"Failed to retrieve a download URL."];
+ }
+ } 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..752c410 100644
--- a/Firebase/Storage/FIRStorageGetMetadataTask.m
+++ b/Firebase/Storage/FIRStorageGetMetadataTask.m
@@ -46,7 +46,7 @@
- (void)enqueue {
NSMutableURLRequest *request = [self.baseRequest mutableCopy];
request.HTTPMethod = @"GET";
- request.timeoutInterval = self.reference.storage.maxDownloadRetryTime;
+ request.timeoutInterval = self.reference.storage.maxOperationRetryTime;
FIRStorageVoidMetadataError callback = _completion;
_completion = nil;
@@ -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<NSString *> *downloadStringArray = [downloadTokens componentsSeparatedByString:@","];
- NSMutableArray<NSURL *> *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..cea4e7d 100644
--- a/Firebase/Storage/FIRStorageUpdateMetadataTask.m
+++ b/Firebase/Storage/FIRStorageUpdateMetadataTask.m
@@ -48,7 +48,7 @@
NSDictionary *updateDictionary = [_updateMetadata updatedMetadata];
NSData *updateData = [NSData frs_dataFromJSONDictionary:updateDictionary];
request.HTTPMethod = @"PATCH";
- request.timeoutInterval = self.reference.storage.maxUploadRetryTime;
+ request.timeoutInterval = self.reference.storage.maxOperationRetryTime;
request.HTTPBody = updateData;
NSString *typeString = @"application/json; charset=UTF-8";
[request setValue:typeString forHTTPHeaderField:@"Content-Type"];
@@ -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..a76a6aa 100644
--- a/Firebase/Storage/Private/FIRStorageErrors.h
+++ b/Firebase/Storage/Private/FIRStorageErrors.h
@@ -44,11 +44,27 @@ 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;
+
+/**
+ * Creates a Firebase Storage error with a custom error message.
+ *
+ * @param errorMessage A custom error message.
+ * @return Returns the corresponding Firebase Storage error.
+ */
++ (NSError *)errorWithCustomMessage:(NSString *)errorMessage;
+
@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..8cd9eb3
--- /dev/null
+++ b/Firebase/Storage/Private/FIRStorageGetDownloadURLTask.h
@@ -0,0 +1,34 @@
+/*
+ * 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 <FIRStorageTaskManagement>
+
+- (instancetype)initWithReference:(FIRStorageReference *)reference
+ fetcherService:(GTMSessionFetcherService *)service
+ completion:(FIRStorageVoidURLError)completion;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Firebase/Storage/Private/FIRStorageGetDownloadURLTask_Private.h b/Firebase/Storage/Private/FIRStorageGetDownloadURLTask_Private.h
new file mode 100644
index 0000000..0da04a4
--- /dev/null
+++ b/Firebase/Storage/Private/FIRStorageGetDownloadURLTask_Private.h
@@ -0,0 +1,31 @@
+/*
+ * 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"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * Task which provides the ability to get a download URL for an object in Firebase Storage.
+ */
+@interface FIRStorageGetDownloadURLTask ()
+
+/** Extracts a download URL from the StorageMetadata dictonary representation. */
++ (nullable 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
@@ -113,12 +113,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<NSURL *> *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