aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firebase/Storage/FIRStorage.m
diff options
context:
space:
mode:
authorGravatar Paul Beusterien <paulbeusterien@google.com>2017-05-15 12:27:07 -0700
committerGravatar Paul Beusterien <paulbeusterien@google.com>2017-05-15 12:27:07 -0700
commit98ba64449a632518bd2b86fe8d927f4a960d3ddc (patch)
tree131d9c4272fa6179fcda6c5a33fcb3b1bd57ad2e /Firebase/Storage/FIRStorage.m
parent32461366c9e204a527ca05e6e9b9404a2454ac51 (diff)
Initial
Diffstat (limited to 'Firebase/Storage/FIRStorage.m')
-rw-r--r--Firebase/Storage/FIRStorage.m233
1 files changed, 233 insertions, 0 deletions
diff --git a/Firebase/Storage/FIRStorage.m b/Firebase/Storage/FIRStorage.m
new file mode 100644
index 0000000..dd11391
--- /dev/null
+++ b/Firebase/Storage/FIRStorage.m
@@ -0,0 +1,233 @@
+// Copyright 2017 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 "FIRStorage.h"
+
+#import "FIRStorageConstants_Private.h"
+#import "FIRStoragePath.h"
+#import "FIRStorageReference.h"
+#import "FIRStorageReference_Private.h"
+#import "FIRStorageTokenAuthorizer.h"
+#import "FIRStorageUtils.h"
+#import "FIRStorage_Private.h"
+
+#import "FIRApp.h"
+#import "FIROptions.h"
+
+#import <GTMSessionFetcher/GTMSessionFetcher.h>
+#import <GTMSessionFetcher/GTMSessionFetcherLogging.h>
+
+static NSMutableDictionary<
+ NSString * /* app name */,
+ NSMutableDictionary<NSString * /* bucket */, GTMSessionFetcherService *> *> *_fetcherServiceMap;
+static GTMSessionFetcherRetryBlock _retryWhenOffline;
+
+@implementation FIRStorage
+
++ (void)initialize {
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ _retryWhenOffline = ^(BOOL suggestedWillRetry,
+ NSError * GTM_NULLABLE_TYPE error,
+ GTMSessionFetcherRetryResponse response) {
+ bool shouldRetry = suggestedWillRetry;
+ // GTMSessionFetcher does not consider being offline a retryable error, but we do, so we
+ // special-case it here.
+ if (!shouldRetry && error) {
+ shouldRetry = error.code == NSURLErrorNotConnectedToInternet;
+ }
+ response(shouldRetry);
+ };
+ _fetcherServiceMap = [[NSMutableDictionary alloc] init];
+ });
+}
+
++ (GTMSessionFetcherService *)fetcherServiceForApp:(FIRApp *)app bucket:(NSString *)bucket {
+ @synchronized(_fetcherServiceMap) {
+ NSMutableDictionary *bucketMap = _fetcherServiceMap[app.name];
+ if (!bucketMap) {
+ bucketMap = [[NSMutableDictionary alloc] init];
+ _fetcherServiceMap[app.name] = bucketMap;
+ }
+
+ GTMSessionFetcherService *fetcherService = bucketMap[bucket];
+ if (!fetcherService) {
+ fetcherService = [[GTMSessionFetcherService alloc] init];
+ [fetcherService setRetryEnabled:YES];
+ [fetcherService setRetryBlock:_retryWhenOffline];
+ FIRStorageTokenAuthorizer *authorizer =
+ [[FIRStorageTokenAuthorizer alloc] initWithApp:app fetcherService:fetcherService];
+ [fetcherService setAuthorizer:authorizer];
+ bucketMap[bucket] = fetcherService;
+ }
+ return fetcherService;
+ }
+}
+
++ (void)setGTMSessionFetcherLoggingEnabled:(BOOL)isLoggingEnabled {
+ [GTMSessionFetcher setLoggingEnabled:isLoggingEnabled];
+}
+
++ (instancetype)storage {
+ return [self storageForApp:[FIRApp defaultApp]];
+}
+
++ (instancetype)storageForApp:(FIRApp *)app {
+ NSString* url;
+
+ if (app.options.storageBucket) {
+ url = [app.options.storageBucket isEqualToString:@""] ? @""
+ : [@"gs://" stringByAppendingString:app.options.storageBucket];
+ }
+
+ return [self storageForApp:app URL:url];
+}
+
++ (instancetype)storageWithURL:(NSString *)url {
+ return [self storageForApp:[FIRApp defaultApp] URL:url];
+}
+
++ (instancetype)storageForApp:(FIRApp *)app URL:(NSString *)url {
+ if (!url) {
+ NSString *const kAppNotConfiguredMessage =
+ @"No default Storage bucket found. Did you configure Firebase Storage properly?";
+ [NSException raise:NSInvalidArgumentException format:kAppNotConfiguredMessage];
+ }
+
+ NSString *bucket;
+ if ([url isEqualToString:@""]) {
+ bucket = @"";
+ } else {
+ FIRStoragePath *path;
+
+ @try {
+ path = [FIRStoragePath pathFromGSURI:url];
+ } @catch (NSException *e) {
+ [NSException raise:NSInternalInconsistencyException
+ format:@"URI must be in the form of gs://<bucket>/"];
+ }
+
+ if (path.object != nil && ![path.object isEqualToString:@""]) {
+ [NSException raise:NSInternalInconsistencyException
+ format:@"Storage bucket cannot be initialized with a path"];
+ }
+
+ bucket = path.bucket;
+ }
+
+ return [[self alloc] initWithApp:app bucket:bucket];
+}
+
+- (instancetype)initWithApp:(FIRApp *)app bucket:(NSString *)bucket {
+ self = [super init];
+ if (self) {
+ _app = app;
+ _storageBucket = bucket;
+ _fetcherServiceForApp = [FIRStorage fetcherServiceForApp:_app bucket:bucket];
+ _maxDownloadRetryTime = 600.0;
+ _maxOperationRetryTime = 120.0;
+ _maxUploadRetryTime = 600.0;
+ }
+ return self;
+}
+
+#pragma mark - NSObject overrides
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ FIRStorage *storage = [[[self class] allocWithZone:zone] initWithApp:_app bucket:_storageBucket];
+ storage.callbackQueue = _callbackQueue;
+ return storage;
+}
+
+// Two FIRStorage objects are equal if they use the same app
+- (BOOL)isEqual:(id)object {
+ if (self == object) {
+ return YES;
+ }
+
+ if (![object isKindOfClass:[FIRStorage class]]) {
+ return NO;
+ }
+
+ BOOL isEqualObject = [self isEqualToFIRStorage:(FIRStorage *)object];
+ return isEqualObject;
+}
+
+- (BOOL)isEqualToFIRStorage:(FIRStorage *)storage {
+ BOOL isEqual = [_app isEqual:storage->_app];
+ return isEqual;
+}
+
+- (NSUInteger)hash {
+ NSUInteger hash = [_app hash] ^ [_callbackQueue hash];
+ return hash;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"%@ %p: %@", [self class], self, _app];
+}
+
+#pragma mark - Public methods
+
+- (FIRStorageReference *)reference {
+ FIRStoragePath *path = [[FIRStoragePath alloc] initWithBucket:_storageBucket object:nil];
+ return [[FIRStorageReference alloc] initWithStorage:self path:path];
+}
+
+- (FIRStorageReference *)referenceForURL:(NSString *)string {
+ FIRStoragePath *path = [FIRStoragePath pathFromString:string];
+
+ // If no default bucket exists (empty string), accept anything.
+ if ([_storageBucket isEqual:@""]) {
+ FIRStorageReference *reference = [[FIRStorageReference alloc] initWithStorage:self path:path];
+ return reference;
+ }
+
+ // If there exists a default bucket, throw if provided a different bucket.
+ if (![path.bucket isEqual:_storageBucket]) {
+ NSString *const kInvalidBucketFormat =
+ @"Provided bucket: %@ does not match the Storage bucket of the current instance: %@";
+ [NSException raise:NSInvalidArgumentException
+ format:kInvalidBucketFormat, path.bucket, _storageBucket];
+ }
+
+ FIRStorageReference *reference = [[FIRStorageReference alloc] initWithStorage:self path:path];
+ return reference;
+}
+
+- (FIRStorageReference *)referenceWithPath:(NSString *)string {
+ FIRStorageReference *reference = [[self reference] child:string];
+ return reference;
+}
+
+- (void)setCallbackQueue:(dispatch_queue_t)callbackQueue {
+ _fetcherServiceForApp.callbackQueue = callbackQueue;
+}
+
+#pragma mark - Background tasks
+
++ (void)enableBackgroundTasks:(BOOL)isEnabled {
+ [NSException raise:NSGenericException format:@"enableBackgroundTasks not implemented"];
+}
+
+- (NSArray<FIRStorageUploadTask *> *)uploadTasks {
+ [NSException raise:NSGenericException format:@"getUploadTasks not implemented"];
+ return nil;
+}
+
+- (NSArray<FIRStorageDownloadTask *> *)downloadTasks {
+ [NSException raise:NSGenericException format:@"getDownloadTasks not implemented"];
+ return nil;
+}
+@end