adding pods method of package managing
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
@protocol FIRAppCheckTokenResultInterop;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AppCheckTokenHandlerInterop)
|
||||
typedef void (^FIRAppCheckTokenHandlerInterop)(id<FIRAppCheckTokenResultInterop> tokenResult);
|
||||
|
||||
@protocol FIRAppCheckInterop <NSObject>
|
||||
|
||||
/// Retrieve a cached or generate a new FAA Token. If forcingRefresh == YES always generates a new
|
||||
/// token and updates the cache.
|
||||
- (void)getTokenForcingRefresh:(BOOL)forcingRefresh
|
||||
completion:(FIRAppCheckTokenHandlerInterop)handler
|
||||
NS_SWIFT_NAME(getToken(forcingRefresh:completion:));
|
||||
|
||||
/// A notification with the specified name is sent to the default notification center
|
||||
/// (`NotificationCenter.default`) each time a Firebase app check token is refreshed.
|
||||
/// The user info dictionary contains `-[self notificationTokenKey]` and
|
||||
/// `-[self notificationAppNameKey]` keys.
|
||||
- (NSString *)tokenDidChangeNotificationName;
|
||||
|
||||
/// `userInfo` key for the FAC token in a notification for `tokenDidChangeNotificationName`.
|
||||
- (NSString *)notificationTokenKey;
|
||||
/// `userInfo` key for the `FirebaseApp.name` in a notification for
|
||||
/// `tokenDidChangeNotificationName`.
|
||||
- (NSString *)notificationAppNameKey;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol FIRAppCheckTokenResultInterop <NSObject>
|
||||
|
||||
/// App Check token in the case of success or a dummy token in the case of a failure.
|
||||
/// In general, the value of the token should always be set to the request header.
|
||||
@property(nonatomic, readonly) NSString *token;
|
||||
|
||||
/// A token fetch error in the case of a failure or `nil` in the case of success.
|
||||
@property(nonatomic, readonly, nullable) NSError *error;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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 <FirebaseCore/FIRApp.h>
|
||||
|
||||
@class FIRComponentContainer;
|
||||
@protocol FIRLibrary;
|
||||
|
||||
/**
|
||||
* The internal interface to FIRApp. This is meant for first-party integrators, who need to receive
|
||||
* FIRApp notifications, log info about the success or failure of their configuration, and access
|
||||
* other internal functionality of FIRApp.
|
||||
*
|
||||
* TODO(b/28296561): Restructure this header.
|
||||
*/
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NS_ENUM(NSInteger, FIRConfigType) {
|
||||
FIRConfigTypeCore = 1,
|
||||
FIRConfigTypeSDK = 2,
|
||||
};
|
||||
|
||||
extern NSString *const kFIRDefaultAppName;
|
||||
extern NSString *const kFIRAppReadyToConfigureSDKNotification;
|
||||
extern NSString *const kFIRAppDeleteNotification;
|
||||
extern NSString *const kFIRAppIsDefaultAppKey;
|
||||
extern NSString *const kFIRAppNameKey;
|
||||
extern NSString *const kFIRGoogleAppIDKey;
|
||||
extern NSString *const kFirebaseCoreErrorDomain;
|
||||
|
||||
/** The NSUserDefaults suite name for FirebaseCore, for those storage locations that use it. */
|
||||
extern NSString *const kFirebaseCoreDefaultsSuiteName;
|
||||
|
||||
/**
|
||||
* The format string for the User Defaults key used for storing the data collection enabled flag.
|
||||
* This includes formatting to append the Firebase App's name.
|
||||
*/
|
||||
extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat;
|
||||
|
||||
/**
|
||||
* The plist key used for storing the data collection enabled flag.
|
||||
*/
|
||||
extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey;
|
||||
|
||||
/** @var FIRAuthStateDidChangeInternalNotification
|
||||
@brief The name of the @c NSNotificationCenter notification which is posted when the auth state
|
||||
changes (e.g. a new token has been produced, a user logs in or out). The object parameter of
|
||||
the notification is a dictionary possibly containing the key:
|
||||
@c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not
|
||||
contain this key it indicates a sign-out event took place.
|
||||
*/
|
||||
extern NSString *const FIRAuthStateDidChangeInternalNotification;
|
||||
|
||||
/** @var FIRAuthStateDidChangeInternalNotificationTokenKey
|
||||
@brief A key present in the dictionary object parameter of the
|
||||
@c FIRAuthStateDidChangeInternalNotification notification. The value associated with this
|
||||
key will contain the new access token.
|
||||
*/
|
||||
extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey;
|
||||
|
||||
/** @var FIRAuthStateDidChangeInternalNotificationAppKey
|
||||
@brief A key present in the dictionary object parameter of the
|
||||
@c FIRAuthStateDidChangeInternalNotification notification. The value associated with this
|
||||
key will contain the FIRApp associated with the auth instance.
|
||||
*/
|
||||
extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey;
|
||||
|
||||
/** @var FIRAuthStateDidChangeInternalNotificationUIDKey
|
||||
@brief A key present in the dictionary object parameter of the
|
||||
@c FIRAuthStateDidChangeInternalNotification notification. The value associated with this
|
||||
key will contain the new user's UID (or nil if there is no longer a user signed in).
|
||||
*/
|
||||
extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey;
|
||||
|
||||
@interface FIRApp ()
|
||||
|
||||
/**
|
||||
* A flag indicating if this is the default app (has the default app name).
|
||||
*/
|
||||
@property(nonatomic, readonly) BOOL isDefaultApp;
|
||||
|
||||
/*
|
||||
* The container of interop SDKs for this app.
|
||||
*/
|
||||
@property(nonatomic) FIRComponentContainer *container;
|
||||
|
||||
/**
|
||||
* Checks if the default app is configured without trying to configure it.
|
||||
*/
|
||||
+ (BOOL)isDefaultAppConfigured;
|
||||
|
||||
/**
|
||||
* Registers a given third-party library with the given version number to be reported for
|
||||
* analytics.
|
||||
*
|
||||
* @param name Name of the library.
|
||||
* @param version Version of the library.
|
||||
*/
|
||||
+ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version;
|
||||
|
||||
/**
|
||||
* Registers a given internal library to be reported for analytics.
|
||||
*
|
||||
* @param library Optional parameter for component registration.
|
||||
* @param name Name of the library.
|
||||
*/
|
||||
+ (void)registerInternalLibrary:(nonnull Class<FIRLibrary>)library
|
||||
withName:(nonnull NSString *)name;
|
||||
|
||||
/**
|
||||
* Registers a given internal library with the given version number to be reported for
|
||||
* analytics. This should only be used for non-Firebase libraries that have their own versioning
|
||||
* scheme.
|
||||
*
|
||||
* @param library Optional parameter for component registration.
|
||||
* @param name Name of the library.
|
||||
* @param version Version of the library.
|
||||
*/
|
||||
+ (void)registerInternalLibrary:(nonnull Class<FIRLibrary>)library
|
||||
withName:(nonnull NSString *)name
|
||||
withVersion:(nonnull NSString *)version;
|
||||
|
||||
/**
|
||||
* A concatenated string representing all the third-party libraries and version numbers.
|
||||
*/
|
||||
+ (NSString *)firebaseUserAgent;
|
||||
|
||||
/**
|
||||
* Can be used by the unit tests in eack SDK to reset FIRApp. This method is thread unsafe.
|
||||
*/
|
||||
+ (void)resetApps;
|
||||
|
||||
/**
|
||||
* Can be used by the unit tests in each SDK to set customized options.
|
||||
*/
|
||||
- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
@class FIRApp;
|
||||
@class FIRComponentContainer;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// Provides a system to clean up cached instances returned from the component system.
|
||||
NS_SWIFT_NAME(ComponentLifecycleMaintainer)
|
||||
@protocol FIRComponentLifecycleMaintainer
|
||||
/// The associated app will be deleted, clean up any resources as they are about to be deallocated.
|
||||
- (void)appWillBeDeleted:(FIRApp *)app;
|
||||
@end
|
||||
|
||||
typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *container,
|
||||
BOOL *isCacheable)
|
||||
NS_SWIFT_NAME(ComponentCreationBlock);
|
||||
|
||||
@class FIRDependency;
|
||||
|
||||
/// Describes the timing of instantiation. Note: new components should default to lazy unless there
|
||||
/// is a strong reason to be eager.
|
||||
typedef NS_ENUM(NSInteger, FIRInstantiationTiming) {
|
||||
FIRInstantiationTimingLazy,
|
||||
FIRInstantiationTimingAlwaysEager,
|
||||
FIRInstantiationTimingEagerInDefaultApp
|
||||
} NS_SWIFT_NAME(InstantiationTiming);
|
||||
|
||||
/// A component that can be used from other Firebase SDKs.
|
||||
NS_SWIFT_NAME(Component)
|
||||
@interface FIRComponent : NSObject
|
||||
|
||||
/// The protocol describing functionality provided from the Component.
|
||||
@property(nonatomic, strong, readonly) Protocol *protocol;
|
||||
|
||||
/// The timing of instantiation.
|
||||
@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming;
|
||||
|
||||
/// An array of dependencies for the component.
|
||||
@property(nonatomic, copy, readonly) NSArray<FIRDependency *> *dependencies;
|
||||
|
||||
/// A block to instantiate an instance of the component with the appropriate dependencies.
|
||||
@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock;
|
||||
|
||||
// There's an issue with long NS_SWIFT_NAMES that causes compilation to fail, disable clang-format
|
||||
// for the next two methods.
|
||||
// clang-format off
|
||||
|
||||
/// Creates a component with no dependencies that will be lazily initialized.
|
||||
+ (instancetype)componentWithProtocol:(Protocol *)protocol
|
||||
creationBlock:(FIRComponentCreationBlock)creationBlock
|
||||
NS_SWIFT_NAME(init(_:creationBlock:));
|
||||
|
||||
/// Creates a component to be registered with the component container.
|
||||
///
|
||||
/// @param protocol - The protocol describing functionality provided by the component.
|
||||
/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's
|
||||
/// a good reason to be instantiated earlier.
|
||||
/// @param dependencies - Any dependencies the `implementingClass` has, optional or required.
|
||||
/// @param creationBlock - A block to instantiate the component with a container, and if
|
||||
/// @return A component that can be registered with the component container.
|
||||
+ (instancetype)componentWithProtocol:(Protocol *)protocol
|
||||
instantiationTiming:(FIRInstantiationTiming)instantiationTiming
|
||||
dependencies:(NSArray<FIRDependency *> *)dependencies
|
||||
creationBlock:(FIRComponentCreationBlock)creationBlock
|
||||
NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:));
|
||||
|
||||
// clang-format on
|
||||
|
||||
/// Unavailable.
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// A type-safe macro to retrieve a component from a container. This should be used to retrieve
|
||||
/// components instead of using the container directly.
|
||||
#define FIR_COMPONENT(type, container) \
|
||||
[FIRComponentType<id<type>> instanceForProtocol:@protocol(type) inContainer:container]
|
||||
|
||||
@class FIRApp;
|
||||
|
||||
/// A container that holds different components that are registered via the
|
||||
/// `registerAsComponentRegistrant:` call. These classes should conform to `FIRComponentRegistrant`
|
||||
/// in order to properly register components for Core.
|
||||
NS_SWIFT_NAME(FirebaseComponentContainer)
|
||||
@interface FIRComponentContainer : NSObject
|
||||
|
||||
/// A weak reference to the app that an instance of the container belongs to.
|
||||
@property(nonatomic, weak, readonly) FIRApp *app;
|
||||
|
||||
/// Unavailable. Use the `container` property on `FIRApp`.
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
@class FIRComponentContainer;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// Do not use directly. A placeholder type in order to provide a macro that will warn users of
|
||||
/// mis-matched protocols.
|
||||
NS_SWIFT_NAME(ComponentType)
|
||||
@interface FIRComponentType<__covariant T> : NSObject
|
||||
|
||||
/// Do not use directly. A factory method to retrieve an instance that provides a specific
|
||||
/// functionality.
|
||||
+ (T)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2019 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 <Foundation/Foundation.h>
|
||||
|
||||
@class FIRDiagnosticsData;
|
||||
@class FIROptions;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** Connects FIRCore with the CoreDiagnostics library. */
|
||||
@interface FIRCoreDiagnosticsConnector : NSObject
|
||||
|
||||
/** Logs FirebaseCore related data.
|
||||
*
|
||||
* @param options The options object containing data to log.
|
||||
*/
|
||||
+ (void)logCoreTelemetryWithOptions:(FIROptions *)options;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// A dependency on a specific protocol's functionality.
|
||||
NS_SWIFT_NAME(Dependency)
|
||||
@interface FIRDependency : NSObject
|
||||
|
||||
/// The protocol describing functionality being depended on.
|
||||
@property(nonatomic, strong, readonly) Protocol *protocol;
|
||||
|
||||
/// A flag to specify if the dependency is required or not.
|
||||
@property(nonatomic, readonly) BOOL isRequired;
|
||||
|
||||
/// Initializes a dependency that is required. Calls `initWithProtocol:isRequired` with `YES` for
|
||||
/// the required parameter.
|
||||
/// Creates a required dependency on the specified protocol's functionality.
|
||||
+ (instancetype)dependencyWithProtocol:(Protocol *)protocol;
|
||||
|
||||
/// Creates a dependency on the specified protocol's functionality and specify if it's required for
|
||||
/// the class's functionality.
|
||||
+ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required;
|
||||
|
||||
/// Use `dependencyWithProtocol:isRequired:` instead.
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2019 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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FIRHeartbeatInfo : NSObject
|
||||
|
||||
// Enum representing the different heartbeat codes.
|
||||
typedef NS_ENUM(NSInteger, FIRHeartbeatInfoCode) {
|
||||
FIRHeartbeatInfoCodeNone = 0,
|
||||
FIRHeartbeatInfoCodeSDK = 1,
|
||||
FIRHeartbeatInfoCodeGlobal = 2,
|
||||
FIRHeartbeatInfoCodeCombined = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* Get heartbeat code required for the sdk.
|
||||
* @param heartbeatTag String representing the sdk heartbeat tag.
|
||||
* @return Heartbeat code indicating whether or not an sdk/global heartbeat
|
||||
* needs to be sent
|
||||
*/
|
||||
+ (FIRHeartbeatInfoCode)heartbeatCodeForTag:(NSString *)heartbeatTag;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef FIRLibrary_h
|
||||
#define FIRLibrary_h
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class FIRApp;
|
||||
@class FIRComponent;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// Provide an interface to register a library for userAgent logging and availability to others.
|
||||
NS_SWIFT_NAME(Library)
|
||||
@protocol FIRLibrary
|
||||
|
||||
/// Returns one or more FIRComponents that will be registered in
|
||||
/// FIRApp and participate in dependency resolution and injection.
|
||||
+ (NSArray<FIRComponent *> *)componentsToRegister;
|
||||
|
||||
@optional
|
||||
/// Implement this method if the library needs notifications for lifecycle events. This method is
|
||||
/// called when the developer calls `FirebaseApp.configure()`.
|
||||
+ (void)configureWithApp:(FIRApp *)app;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif /* FIRLibrary_h */
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
#import <FirebaseCore/FIRLoggerLevel.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* The Firebase services used in Firebase logger.
|
||||
*/
|
||||
typedef NSString *const FIRLoggerService;
|
||||
|
||||
extern FIRLoggerService kFIRLoggerAnalytics;
|
||||
extern FIRLoggerService kFIRLoggerCrash;
|
||||
extern FIRLoggerService kFIRLoggerCore;
|
||||
extern FIRLoggerService kFIRLoggerRemoteConfig;
|
||||
|
||||
/**
|
||||
* The key used to store the logger's error count.
|
||||
*/
|
||||
extern NSString *const kFIRLoggerErrorCountKey;
|
||||
|
||||
/**
|
||||
* The key used to store the logger's warning count.
|
||||
*/
|
||||
extern NSString *const kFIRLoggerWarningCountKey;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
/**
|
||||
* Enables or disables Analytics debug mode.
|
||||
* If set to YES, the logging level for Analytics will be set to FIRLoggerLevelDebug.
|
||||
* Enabling the debug mode has no effect if the app is running from App Store.
|
||||
* (required) analytics debug mode flag.
|
||||
*/
|
||||
void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode);
|
||||
|
||||
/**
|
||||
* Changes the default logging level of FIRLoggerLevelNotice to a user-specified level.
|
||||
* The default level cannot be set above FIRLoggerLevelNotice if the app is running from App Store.
|
||||
* (required) log level (one of the FIRLoggerLevel enum values).
|
||||
*/
|
||||
void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel);
|
||||
|
||||
/**
|
||||
* Checks if the specified logger level is loggable given the current settings.
|
||||
* (required) log level (one of the FIRLoggerLevel enum values).
|
||||
* (required) whether or not this function is called from the Analytics component.
|
||||
*/
|
||||
BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent);
|
||||
|
||||
/**
|
||||
* Logs a message to the Xcode console and the device log. If running from AppStore, will
|
||||
* not log any messages with a level higher than FIRLoggerLevelNotice to avoid log spamming.
|
||||
* (required) log level (one of the FIRLoggerLevel enum values).
|
||||
* (required) service name of type FIRLoggerService.
|
||||
* (required) message code starting with "I-" which means iOS, followed by a capitalized
|
||||
* three-character service identifier and a six digit integer message ID that is unique
|
||||
* within the service.
|
||||
* An example of the message code is @"I-COR000001".
|
||||
* (required) message string which can be a format string.
|
||||
* (optional) variable arguments list obtained from calling va_start, used when message is a format
|
||||
* string.
|
||||
*/
|
||||
extern void FIRLogBasic(FIRLoggerLevel level,
|
||||
FIRLoggerService service,
|
||||
NSString *messageCode,
|
||||
NSString *message,
|
||||
// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable
|
||||
// See: http://stackoverflow.com/q/29095469
|
||||
#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX
|
||||
va_list args_ptr
|
||||
#else
|
||||
va_list _Nullable args_ptr
|
||||
#endif
|
||||
);
|
||||
|
||||
/**
|
||||
* The following functions accept the following parameters in order:
|
||||
* (required) service name of type FIRLoggerService.
|
||||
* (required) message code starting from "I-" which means iOS, followed by a capitalized
|
||||
* three-character service identifier and a six digit integer message ID that is unique
|
||||
* within the service.
|
||||
* An example of the message code is @"I-COR000001".
|
||||
* See go/firebase-log-proposal for details.
|
||||
* (required) message string which can be a format string.
|
||||
* (optional) the list of arguments to substitute into the format string.
|
||||
* Example usage:
|
||||
* FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name);
|
||||
*/
|
||||
extern void FIRLogError(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
|
||||
NS_FORMAT_FUNCTION(3, 4);
|
||||
extern void FIRLogWarning(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
|
||||
NS_FORMAT_FUNCTION(3, 4);
|
||||
extern void FIRLogNotice(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
|
||||
NS_FORMAT_FUNCTION(3, 4);
|
||||
extern void FIRLogInfo(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
|
||||
NS_FORMAT_FUNCTION(3, 4);
|
||||
extern void FIRLogDebug(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
|
||||
NS_FORMAT_FUNCTION(3, 4);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
@interface FIRLoggerWrapper : NSObject
|
||||
|
||||
/**
|
||||
* Objective-C wrapper for FIRLogBasic to allow weak linking to FIRLogger
|
||||
* (required) log level (one of the FIRLoggerLevel enum values).
|
||||
* (required) service name of type FIRLoggerService.
|
||||
* (required) message code starting with "I-" which means iOS, followed by a capitalized
|
||||
* three-character service identifier and a six digit integer message ID that is unique
|
||||
* within the service.
|
||||
* An example of the message code is @"I-COR000001".
|
||||
* (required) message string which can be a format string.
|
||||
* (optional) variable arguments list obtained from calling va_start, used when message is a format
|
||||
* string.
|
||||
*/
|
||||
|
||||
+ (void)logWithLevel:(FIRLoggerLevel)level
|
||||
withService:(FIRLoggerService)service
|
||||
withCode:(NSString *)messageCode
|
||||
withMessage:(NSString *)message
|
||||
withArgs:(va_list)args;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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 <FirebaseCore/FIROptions.h>
|
||||
|
||||
/**
|
||||
* Keys for the strings in the plist file.
|
||||
*/
|
||||
extern NSString *const kFIRAPIKey;
|
||||
extern NSString *const kFIRTrackingID;
|
||||
extern NSString *const kFIRGoogleAppID;
|
||||
extern NSString *const kFIRClientID;
|
||||
extern NSString *const kFIRGCMSenderID;
|
||||
extern NSString *const kFIRAndroidClientID;
|
||||
extern NSString *const kFIRDatabaseURL;
|
||||
extern NSString *const kFIRStorageBucket;
|
||||
extern NSString *const kFIRBundleID;
|
||||
extern NSString *const kFIRProjectID;
|
||||
|
||||
/**
|
||||
* Keys for the plist file name
|
||||
*/
|
||||
extern NSString *const kServiceInfoFileName;
|
||||
|
||||
extern NSString *const kServiceInfoFileType;
|
||||
|
||||
/**
|
||||
* This header file exposes the initialization of FIROptions to internal use.
|
||||
*/
|
||||
@interface FIROptions ()
|
||||
|
||||
/**
|
||||
* resetDefaultOptions and initInternalWithOptionsDictionary: are exposed only for unit tests.
|
||||
*/
|
||||
+ (void)resetDefaultOptions;
|
||||
|
||||
/**
|
||||
* Initializes the options with dictionary. The above strings are the keys of the dictionary.
|
||||
* This is the designated initializer.
|
||||
*/
|
||||
- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)serviceInfoDictionary
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
* defaultOptions and defaultOptionsDictionary are exposed in order to be used in FIRApp and
|
||||
* other first party services.
|
||||
*/
|
||||
+ (FIROptions *)defaultOptions;
|
||||
|
||||
+ (NSDictionary *)defaultOptionsDictionary;
|
||||
|
||||
/**
|
||||
* Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at
|
||||
* runtime.
|
||||
*/
|
||||
@property(nonatomic, readonly) BOOL isAnalyticsCollectionExplicitlySet;
|
||||
|
||||
/**
|
||||
* Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless
|
||||
* explicitly disabled in GoogleService-Info.plist.
|
||||
*/
|
||||
@property(nonatomic, readonly) BOOL isAnalyticsCollectionEnabled;
|
||||
|
||||
/**
|
||||
* Whether or not Analytics Collection was completely disabled. If YES, then
|
||||
* isAnalyticsCollectionEnabled will be NO.
|
||||
*/
|
||||
@property(nonatomic, readonly) BOOL isAnalyticsCollectionDeactivated;
|
||||
|
||||
/**
|
||||
* The version ID of the client library, e.g. @"1100000".
|
||||
*/
|
||||
@property(nonatomic, readonly, copy) NSString *libraryVersionID;
|
||||
|
||||
/**
|
||||
* The flag indicating whether this object was constructed with the values in the default plist
|
||||
* file.
|
||||
*/
|
||||
@property(nonatomic) BOOL usingOptionsFromDefaultPlist;
|
||||
|
||||
/**
|
||||
* Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in
|
||||
* GoogleService-Info.plist.
|
||||
*/
|
||||
@property(nonatomic, readonly) BOOL isMeasurementEnabled;
|
||||
|
||||
/**
|
||||
* Whether or not Analytics was enabled in the developer console.
|
||||
*/
|
||||
@property(nonatomic, readonly) BOOL isAnalyticsEnabled;
|
||||
|
||||
/**
|
||||
* Whether or not SignIn was enabled in the developer console.
|
||||
*/
|
||||
@property(nonatomic, readonly) BOOL isSignInEnabled;
|
||||
|
||||
/**
|
||||
* Whether or not editing is locked. This should occur after FIROptions has been set on a FIRApp.
|
||||
*/
|
||||
@property(nonatomic, getter=isEditingLocked) BOOL editingLocked;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// 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.
|
||||
|
||||
// An umbrella header, for any other libraries in this repo to access Firebase Public and Private
|
||||
// headers. Any package manager complexity should be handled here.
|
||||
|
||||
#import <FirebaseCore/FirebaseCore.h>
|
||||
|
||||
#import "FirebaseCore/Sources/Private/FIRAppInternal.h"
|
||||
#import "FirebaseCore/Sources/Private/FIRComponent.h"
|
||||
#import "FirebaseCore/Sources/Private/FIRComponentContainer.h"
|
||||
#import "FirebaseCore/Sources/Private/FIRComponentType.h"
|
||||
#import "FirebaseCore/Sources/Private/FIRDependency.h"
|
||||
#import "FirebaseCore/Sources/Private/FIRHeartbeatInfo.h"
|
||||
#import "FirebaseCore/Sources/Private/FIRLibrary.h"
|
||||
#import "FirebaseCore/Sources/Private/FIRLogger.h"
|
||||
#import "FirebaseCore/Sources/Private/FIROptionsInternal.h"
|
||||
@@ -0,0 +1,373 @@
|
||||
// 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorage.h"
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageReference.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageComponent.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStoragePath.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageReference_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageTokenAuthorizer.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageUtils.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorage_Private.h"
|
||||
|
||||
#import "FirebaseAppCheck/Sources/Interop/FIRAppCheckInterop.h"
|
||||
#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"
|
||||
#import "Interop/Auth/Public/FIRAuthInterop.h"
|
||||
|
||||
#if SWIFT_PACKAGE
|
||||
@import GTMSessionFetcherCore;
|
||||
#else
|
||||
#import <GTMSessionFetcher/GTMSessionFetcher.h>
|
||||
#import <GTMSessionFetcher/GTMSessionFetcherLogging.h>
|
||||
#endif
|
||||
|
||||
static NSMutableDictionary<
|
||||
NSString * /* app name */,
|
||||
NSMutableDictionary<NSString * /* bucket */, GTMSessionFetcherService *> *> *_fetcherServiceMap;
|
||||
static GTMSessionFetcherRetryBlock _retryWhenOffline;
|
||||
|
||||
@interface FIRStorage () {
|
||||
/// Stored Auth reference, if it exists. This needs to be stored for `copyWithZone:`.
|
||||
id<FIRAuthInterop> _Nullable _auth;
|
||||
id<FIRAppCheckInterop> _Nullable _appCheck;
|
||||
BOOL _usesEmulator;
|
||||
NSTimeInterval _maxUploadRetryTime;
|
||||
NSTimeInterval _maxDownloadRetryTime;
|
||||
NSTimeInterval _maxOperationRetryTime;
|
||||
}
|
||||
@end
|
||||
|
||||
@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
|
||||
auth:(nullable id<FIRAuthInterop>)auth
|
||||
appCheck:(nullable id<FIRAppCheckInterop>)appCheck {
|
||||
@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];
|
||||
[fetcherService setAllowLocalhostRequest:YES];
|
||||
FIRStorageTokenAuthorizer *authorizer =
|
||||
[[FIRStorageTokenAuthorizer alloc] initWithGoogleAppID:app.options.googleAppID
|
||||
fetcherService:fetcherService
|
||||
authProvider:auth
|
||||
appCheck:appCheck];
|
||||
[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 {
|
||||
if (app.options.storageBucket) {
|
||||
NSString *url = [app.options.storageBucket isEqualToString:@""]
|
||||
? @""
|
||||
: [@"gs://" stringByAppendingString:app.options.storageBucket];
|
||||
return [self storageForApp:app URL:url];
|
||||
} else {
|
||||
NSString *const kAppNotConfiguredMessage =
|
||||
@"No default Storage bucket found. Did you configure Firebase Storage properly?";
|
||||
[NSException raise:NSInvalidArgumentException format:kAppNotConfiguredMessage];
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
+ (instancetype)storageWithURL:(NSString *)url {
|
||||
return [self storageForApp:[FIRApp defaultApp] URL:url];
|
||||
}
|
||||
|
||||
+ (instancetype)storageForApp:(FIRApp *)app URL:(NSString *)url {
|
||||
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;
|
||||
}
|
||||
|
||||
// Retrieve the instance provider from the app's container to inject dependencies as needed.
|
||||
id<FIRStorageMultiBucketProvider> provider =
|
||||
FIR_COMPONENT(FIRStorageMultiBucketProvider, app.container);
|
||||
return [provider storageForBucket:bucket];
|
||||
}
|
||||
|
||||
- (instancetype)initWithApp:(FIRApp *)app
|
||||
bucket:(NSString *)bucket
|
||||
auth:(nullable id<FIRAuthInterop>)auth
|
||||
appCheck:(nullable id<FIRAppCheckInterop>)appCheck {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_app = app;
|
||||
_auth = auth;
|
||||
_appCheck = appCheck;
|
||||
_storageBucket = bucket;
|
||||
_host = kFIRStorageHost;
|
||||
_scheme = kFIRStorageScheme;
|
||||
_port = @(kFIRStoragePort);
|
||||
_fetcherServiceForApp = nil; // Configured in `ensureConfigured()`
|
||||
// Must be a serial queue.
|
||||
_dispatchQueue = dispatch_queue_create("com.google.firebase.storage", DISPATCH_QUEUE_SERIAL);
|
||||
_maxDownloadRetryTime = 600.0;
|
||||
_maxDownloadRetryInterval =
|
||||
[FIRStorageUtils computeRetryIntervalFromRetryTime:_maxDownloadRetryTime];
|
||||
_maxOperationRetryTime = 120.0;
|
||||
_maxOperationRetryInterval =
|
||||
[FIRStorageUtils computeRetryIntervalFromRetryTime:_maxOperationRetryTime];
|
||||
_maxUploadRetryTime = 600.0;
|
||||
_maxUploadRetryInterval =
|
||||
[FIRStorageUtils computeRetryIntervalFromRetryTime:_maxUploadRetryTime];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
NSAssert(false, @"Storage cannot be directly instantiated, use "
|
||||
"Storage.storage() or Storage.storage(app:) instead");
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark - NSObject overrides
|
||||
|
||||
- (instancetype)copyWithZone:(NSZone *)zone {
|
||||
FIRStorage *storage = [[[self class] allocWithZone:zone] initWithApp:_app
|
||||
bucket:_storageBucket
|
||||
auth:_auth
|
||||
appCheck:_appCheck];
|
||||
storage.callbackQueue = self.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] && [_storageBucket isEqualToString:storage.storageBucket];
|
||||
return isEqual;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
NSUInteger hash = [_app hash] ^ [self.callbackQueue hash];
|
||||
return hash;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"%@ %p: %@", [self class], self, _app];
|
||||
}
|
||||
|
||||
#pragma mark - Retry time intervals
|
||||
|
||||
- (void)setMaxUploadRetryTime:(NSTimeInterval)maxUploadRetryTime {
|
||||
@synchronized(self) {
|
||||
_maxUploadRetryTime = maxUploadRetryTime;
|
||||
_maxUploadRetryInterval =
|
||||
[FIRStorageUtils computeRetryIntervalFromRetryTime:maxUploadRetryTime];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSTimeInterval)maxDownloadRetryTime {
|
||||
@synchronized(self) {
|
||||
return _maxDownloadRetryTime;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setMaxDownloadRetryTime:(NSTimeInterval)maxDownloadRetryTime {
|
||||
@synchronized(self) {
|
||||
_maxDownloadRetryTime = maxDownloadRetryTime;
|
||||
_maxDownloadRetryInterval =
|
||||
[FIRStorageUtils computeRetryIntervalFromRetryTime:maxDownloadRetryTime];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSTimeInterval)maxUploadRetryTime {
|
||||
@synchronized(self) {
|
||||
return _maxUploadRetryTime;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setMaxOperationRetryTime:(NSTimeInterval)maxOperationRetryTime {
|
||||
@synchronized(self) {
|
||||
_maxOperationRetryTime = maxOperationRetryTime;
|
||||
_maxOperationRetryInterval =
|
||||
[FIRStorageUtils computeRetryIntervalFromRetryTime:maxOperationRetryTime];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSTimeInterval)maxOperationRetryTime {
|
||||
@synchronized(self) {
|
||||
return _maxOperationRetryTime;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Public methods
|
||||
|
||||
- (FIRStorageReference *)reference {
|
||||
[self ensureConfigured];
|
||||
|
||||
FIRStoragePath *path = [[FIRStoragePath alloc] initWithBucket:_storageBucket object:nil];
|
||||
return [[FIRStorageReference alloc] initWithStorage:self path:path];
|
||||
}
|
||||
|
||||
- (FIRStorageReference *)referenceForURL:(NSString *)string {
|
||||
[self ensureConfigured];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
- (dispatch_queue_t)callbackQueue {
|
||||
[self ensureConfigured];
|
||||
return _fetcherServiceForApp.callbackQueue;
|
||||
}
|
||||
|
||||
- (void)setCallbackQueue:(dispatch_queue_t)callbackQueue {
|
||||
[self ensureConfigured];
|
||||
_fetcherServiceForApp.callbackQueue = callbackQueue;
|
||||
}
|
||||
|
||||
- (void)useEmulatorWithHost:(NSString *)host port:(NSInteger)port {
|
||||
if (host.length == 0) {
|
||||
[NSException raise:NSInvalidArgumentException format:@"Cannot connect to nil or empty host."];
|
||||
}
|
||||
|
||||
if (port < 0) {
|
||||
[NSException raise:NSInvalidArgumentException
|
||||
format:@"Port must be greater than or equal to zero."];
|
||||
}
|
||||
|
||||
if (_fetcherServiceForApp != nil) {
|
||||
[NSException raise:NSInternalInconsistencyException
|
||||
format:@"Cannot connect to emulator after Storage SDK initialization. "
|
||||
@"Call useEmulator(host:port:) before creating a Storage "
|
||||
@"reference or trying to load data."];
|
||||
}
|
||||
|
||||
_usesEmulator = YES;
|
||||
_scheme = @"http";
|
||||
_host = host;
|
||||
_port = @(port);
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
- (void)ensureConfigured {
|
||||
if (!_fetcherServiceForApp) {
|
||||
_fetcherServiceForApp = [FIRStorage fetcherServiceForApp:_app
|
||||
bucket:_storageBucket
|
||||
auth:_auth
|
||||
appCheck:_appCheck];
|
||||
if (_usesEmulator) {
|
||||
_fetcherServiceForApp.allowLocalhostRequest = YES;
|
||||
_fetcherServiceForApp.allowedInsecureSchemes = @[ @"http" ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,45 @@
|
||||
// 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 <Foundation/Foundation.h>
|
||||
|
||||
@class FIRApp;
|
||||
@class FIRStorage;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// This protocol is used in the interop registration process to register an instance provider for
|
||||
/// individual FIRApps.
|
||||
@protocol FIRStorageMultiBucketProvider
|
||||
|
||||
/// Default method for creating a Storage instance.
|
||||
- (FIRStorage *)storageForBucket:(NSString *)bucket;
|
||||
|
||||
@end
|
||||
|
||||
/// A concrete implementation for FIRStorageMultiBucketProvider to create Storage instances.
|
||||
@interface FIRStorageComponent : NSObject <FIRStorageMultiBucketProvider>
|
||||
|
||||
/// The FIRApp that instances will be set up with.
|
||||
@property(nonatomic, weak, readonly) FIRApp *app;
|
||||
|
||||
/// Default method for creating a Storage instance.
|
||||
- (FIRStorage *)storageForBucket:(NSString *)bucket;
|
||||
|
||||
/// Unavailable, use `storageForApp:storageURL:` instead.
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,102 @@
|
||||
// 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 "FirebaseStorage/Sources/FIRStorageComponent.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorage.h"
|
||||
|
||||
#import "FirebaseAppCheck/Sources/Interop/FIRAppCheckInterop.h"
|
||||
#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"
|
||||
#import "Interop/Auth/Public/FIRAuthInterop.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** A NSMutableDictionary of FirebaseApp name and bucket names to FIRStorage instance. */
|
||||
typedef NSMutableDictionary<NSString *, FIRStorage *> FIRStorageDictionary;
|
||||
|
||||
@interface FIRStorage ()
|
||||
// Surface the internal initializer to create instances of FIRStorage.
|
||||
- (instancetype)initWithApp:(FIRApp *)app
|
||||
bucket:(NSString *)bucket
|
||||
auth:(nullable id<FIRAuthInterop>)auth
|
||||
appCheck:(nullable id<FIRAppCheckInterop>)appCheck;
|
||||
@end
|
||||
|
||||
@interface FIRStorageComponent () <FIRLibrary>
|
||||
@property(nonatomic) FIRStorageDictionary *instances;
|
||||
/// Internal initializer.
|
||||
- (instancetype)initWithApp:(FIRApp *)app;
|
||||
@end
|
||||
|
||||
@implementation FIRStorageComponent
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
- (instancetype)initWithApp:(FIRApp *)app {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_app = app;
|
||||
_instances = [NSMutableDictionary dictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
+ (void)load {
|
||||
[FIRApp registerInternalLibrary:(Class<FIRLibrary>)self withName:@"fire-str"];
|
||||
}
|
||||
|
||||
#pragma mark - FIRComponentRegistrant
|
||||
|
||||
+ (nonnull NSArray<FIRComponent *> *)componentsToRegister {
|
||||
FIRDependency *authDep = [FIRDependency dependencyWithProtocol:@protocol(FIRAuthInterop)
|
||||
isRequired:NO];
|
||||
FIRComponentCreationBlock creationBlock =
|
||||
^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) {
|
||||
*isCacheable = YES;
|
||||
return [[FIRStorageComponent alloc] initWithApp:container.app];
|
||||
};
|
||||
FIRComponent *storageProvider =
|
||||
[FIRComponent componentWithProtocol:@protocol(FIRStorageMultiBucketProvider)
|
||||
instantiationTiming:FIRInstantiationTimingLazy
|
||||
dependencies:@[ authDep ]
|
||||
creationBlock:creationBlock];
|
||||
|
||||
return @[ storageProvider ];
|
||||
}
|
||||
|
||||
#pragma mark - FIRStorageInstanceProvider Conformance
|
||||
|
||||
- (FIRStorage *)storageForBucket:(NSString *)bucket {
|
||||
FIRStorageDictionary *instances = [self instances];
|
||||
@synchronized(instances) {
|
||||
FIRStorage *instance = instances[bucket];
|
||||
if (!instance) {
|
||||
// Create an instance of FIRStorage and return it.
|
||||
id<FIRAuthInterop> auth = FIR_COMPONENT(FIRAuthInterop, self.app.container);
|
||||
id<FIRAppCheckInterop> appCheck = FIR_COMPONENT(FIRAppCheckInterop, self.app.container);
|
||||
instance = [[FIRStorage alloc] initWithApp:self.app
|
||||
bucket:bucket
|
||||
auth:auth
|
||||
appCheck:appCheck];
|
||||
instances[bucket] = instance;
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,87 @@
|
||||
// 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageConstants.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h"
|
||||
|
||||
NSString *const kGCSScheme = @"https";
|
||||
NSString *const kGCSHost = @"www.googleapis.com";
|
||||
NSString *const kGCSUploadPath = @"upload";
|
||||
NSString *const kGCSStorageVersionPath = @"storage/v1";
|
||||
NSString *const kGCSBucketPathFormat = @"b/%@";
|
||||
NSString *const kGCSObjectPathFormat = @"o/%@";
|
||||
|
||||
NSString *const kFIRStorageScheme = @"https";
|
||||
NSString *const kFIRStorageHost = @"firebasestorage.googleapis.com";
|
||||
NSInteger const kFIRStoragePort = 443;
|
||||
NSString *const kFIRStorageVersionPath = @"v0";
|
||||
NSString *const kFIRStorageBucketPathFormat = @"b/%@";
|
||||
NSString *const kFIRStorageObjectPathFormat = @"o/%@";
|
||||
NSString *const kFIRStorageFullPathFormat = @"/v0/b/%@/o/%@";
|
||||
|
||||
NSString *const kFIRStorageAuthTokenFormat = @"Firebase %@";
|
||||
NSString *const kFIRStorageDefaultBucketFormat = @"gs://%@";
|
||||
|
||||
NSString *const kFIRStorageResponseErrorDomain = @"ResponseErrorDomain";
|
||||
NSString *const kFIRStorageResponseErrorCode = @"ResponseErrorCode";
|
||||
NSString *const kFIRStorageResponseBody = @"ResponseBody";
|
||||
|
||||
NSString *const FIRStorageErrorDomain = @"FIRStorageErrorDomain";
|
||||
|
||||
NSString *const kFIRStorageInvalidDataFormat = @"Invalid data returned from the server: %@";
|
||||
NSString *const kFIRStorageInvalidObserverStatus =
|
||||
@"Invalid observer status requested, use one "
|
||||
@"of: FIRStorageTaskStatusPause, Resume, Progress, "
|
||||
@"Complete, or Failure";
|
||||
|
||||
/**
|
||||
* String constants mapping GCS Object#list results to ListResult fields.
|
||||
*/
|
||||
NSString *const kFIRStorageListPrefixes = @"prefixes";
|
||||
NSString *const kFIRStorageListItems = @"items";
|
||||
NSString *const kFIRStorageListItemName = @"name";
|
||||
NSString *const kFIRStorageListPageToken = @"nextPageToken";
|
||||
|
||||
/**
|
||||
* String constants mapping GCS Object#resource mappings to metadata fields.
|
||||
*/
|
||||
NSString *const kFIRStorageMetadataBucket = @"bucket";
|
||||
NSString *const kFIRStorageMetadataCacheControl = @"cacheControl";
|
||||
NSString *const kFIRStorageMetadataContentDisposition = @"contentDisposition";
|
||||
NSString *const kFIRStorageMetadataContentEncoding = @"contentEncoding";
|
||||
NSString *const kFIRStorageMetadataContentLanguage = @"contentLanguage";
|
||||
NSString *const kFIRStorageMetadataContentType = @"contentType";
|
||||
NSString *const kFIRStorageMetadataCustomMetadata = @"metadata";
|
||||
NSString *const kFIRStorageMetadataSize = @"size";
|
||||
NSString *const kFIRStorageMetadataGeneration = @"generation";
|
||||
NSString *const kFIRStorageMetadataMetageneration = @"metageneration";
|
||||
NSString *const kFIRStorageMetadataTimeCreated = @"timeCreated";
|
||||
NSString *const kFIRStorageMetadataUpdated = @"updated";
|
||||
NSString *const kFIRStorageMetadataName = @"name";
|
||||
NSString *const kFIRStorageMetadataDownloadTokens = @"downloadTokens";
|
||||
NSString *const kFIRStorageMetadataMd5Hash = @"md5Hash";
|
||||
|
||||
// TODO: add notification support
|
||||
NSString *const kFIRStorageTaskStatusResumeNotification =
|
||||
@"kFIRStorageTaskStatusResumeNotification";
|
||||
NSString *const kFIRStorageTaskStatusPauseNotification = @"kFIRStorageTaskStatusResumeNotification";
|
||||
NSString *const kFIRStorageTaskStatusProgressNotification =
|
||||
@"kFIRStorageTaskStatusResumeNotification";
|
||||
NSString *const kFIRStorageTaskStatusCompleteNotification =
|
||||
@"kFIRStorageTaskStatusResumeNotification";
|
||||
NSString *const kFIRStorageTaskStatusFailureNotification =
|
||||
@"kFIRStorageTaskStatusResumeNotification";
|
||||
|
||||
NSString *const kFIRStorageBundleIdentifier = @"com.google.firebase.storage";
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
@class FIRStorageMetadata;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
FOUNDATION_EXPORT NSString *const kGCSScheme;
|
||||
FOUNDATION_EXPORT NSString *const kGCSHost;
|
||||
FOUNDATION_EXPORT NSString *const kGCSUploadPath;
|
||||
FOUNDATION_EXPORT NSString *const kGCSStorageVersionPath;
|
||||
FOUNDATION_EXPORT NSString *const kGCSBucketPathFormat;
|
||||
FOUNDATION_EXPORT NSString *const kGCSObjectPathFormat;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageScheme;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageHost;
|
||||
FOUNDATION_EXPORT NSInteger const kFIRStoragePort;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageVersionPath;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageBucketPathFormat;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageObjectPathFormat;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageFullPathFormat;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageAuthTokenFormat;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageDefaultBucketFormat;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageResponseErrorDomain;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageResponseErrorCode;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageResponseBody;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageTaskStatusResumeNotification;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageTaskStatusPauseNotification;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageTaskStatusProgressNotification;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageTaskStatusCompleteNotification;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageTaskStatusFailureNotification;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageListPrefixes;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageListItems;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageListItemName;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageListPageToken;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataBucket;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataCacheControl;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataContentDisposition;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataContentEncoding;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataContentLanguage;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataContentType;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataCustomMetadata;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataSize;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataGeneration;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataMetageneration;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataTimeCreated;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataUpdated;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataName;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataDownloadTokens;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataMd5Hash;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageInvalidDataFormat;
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageInvalidObserverStatus;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const kFIRStorageBundleIdentifier;
|
||||
|
||||
/**
|
||||
* Enum representing the internal state of an upload or download task.
|
||||
*/
|
||||
typedef NS_ENUM(NSInteger, FIRStorageTaskState) {
|
||||
/**
|
||||
* Unknown task state
|
||||
*/
|
||||
FIRStorageTaskStateUnknown,
|
||||
|
||||
/**
|
||||
* Task is being queued is ready to run
|
||||
*/
|
||||
FIRStorageTaskStateQueueing,
|
||||
|
||||
/**
|
||||
* Task is resuming from a paused state
|
||||
*/
|
||||
FIRStorageTaskStateResuming,
|
||||
|
||||
/**
|
||||
* Task is currently running
|
||||
*/
|
||||
FIRStorageTaskStateRunning,
|
||||
|
||||
/**
|
||||
* Task reporting a progress event
|
||||
*/
|
||||
FIRStorageTaskStateProgress,
|
||||
|
||||
/**
|
||||
* Task is pausing
|
||||
*/
|
||||
FIRStorageTaskStatePausing,
|
||||
|
||||
/**
|
||||
* Task is completing successfully
|
||||
*/
|
||||
FIRStorageTaskStateCompleting,
|
||||
|
||||
/**
|
||||
* Task is failing unrecoverably
|
||||
*/
|
||||
FIRStorageTaskStateFailing,
|
||||
|
||||
/**
|
||||
* Task paused successfully
|
||||
*/
|
||||
FIRStorageTaskStatePaused,
|
||||
|
||||
/**
|
||||
* Task cancelled successfully
|
||||
*/
|
||||
FIRStorageTaskStateCancelled,
|
||||
|
||||
/**
|
||||
* Task completed successfully
|
||||
*/
|
||||
FIRStorageTaskStateSuccess,
|
||||
|
||||
/**
|
||||
* Task failed unrecoverably
|
||||
*/
|
||||
FIRStorageTaskStateFailed
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents the various types of metadata: Files or Folders.
|
||||
*/
|
||||
typedef NS_ENUM(NSUInteger, FIRStorageMetadataType) {
|
||||
FIRStorageMetadataTypeUnknown,
|
||||
FIRStorageMetadataTypeFile,
|
||||
FIRStorageMetadataTypeFolder,
|
||||
};
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageTask.h"
|
||||
|
||||
@class GTMSessionFetcherService;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* Task which provides the ability to delete an object in Firebase Storage.
|
||||
*/
|
||||
@interface FIRStorageDeleteTask : FIRStorageTask <FIRStorageTaskManagement>
|
||||
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue
|
||||
completion:(FIRStorageVoidError)completion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,83 @@
|
||||
// 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 "FirebaseStorage/Sources/FIRStorageDeleteTask.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageTask_Private.h"
|
||||
|
||||
@implementation FIRStorageDeleteTask {
|
||||
@private
|
||||
FIRStorageVoidError _completion;
|
||||
}
|
||||
|
||||
@synthesize fetcher = _fetcher;
|
||||
@synthesize fetcherCompletion = _fetcherCompletion;
|
||||
|
||||
- (void)dealloc {
|
||||
[_fetcher stopFetching];
|
||||
}
|
||||
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue
|
||||
completion:(FIRStorageVoidError)completion {
|
||||
self = [super initWithReference:reference fetcherService:service dispatchQueue:queue];
|
||||
if (self) {
|
||||
_completion = [completion copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)enqueue {
|
||||
__weak FIRStorageDeleteTask *weakSelf = self;
|
||||
|
||||
[self dispatchAsync:^() {
|
||||
FIRStorageDeleteTask *strongSelf = weakSelf;
|
||||
|
||||
if (!strongSelf) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy];
|
||||
request.HTTPMethod = @"DELETE";
|
||||
request.timeoutInterval = strongSelf.reference.storage.maxOperationRetryTime;
|
||||
|
||||
FIRStorageVoidError callback = strongSelf->_completion;
|
||||
strongSelf->_completion = nil;
|
||||
|
||||
GTMSessionFetcher *fetcher = [strongSelf.fetcherService fetcherWithRequest:request];
|
||||
strongSelf->_fetcher = fetcher;
|
||||
|
||||
fetcher.comment = @"DeleteTask";
|
||||
|
||||
strongSelf->_fetcherCompletion = ^(NSData *_Nullable data, NSError *_Nullable error) {
|
||||
if (!self.error) {
|
||||
self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference];
|
||||
}
|
||||
if (callback) {
|
||||
callback(self.error);
|
||||
}
|
||||
self->_fetcherCompletion = nil;
|
||||
};
|
||||
|
||||
[fetcher beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) {
|
||||
FIRStorageDeleteTask *strongSelf = weakSelf;
|
||||
if (strongSelf.fetcherCompletion) {
|
||||
strongSelf.fetcherCompletion(data, error);
|
||||
}
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,199 @@
|
||||
// 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageDownloadTask.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageDownloadTask_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageObservableTask_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageTask_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorage_Private.h"
|
||||
|
||||
@implementation FIRStorageDownloadTask
|
||||
|
||||
@synthesize progress = _progress;
|
||||
@synthesize fetcher = _fetcher;
|
||||
@synthesize fetcherCompletion = _fetcherCompletion;
|
||||
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue
|
||||
file:(nullable NSURL *)fileURL {
|
||||
self = [super initWithReference:reference fetcherService:service dispatchQueue:queue];
|
||||
if (self) {
|
||||
_fileURL = [fileURL copy];
|
||||
_progress = [NSProgress progressWithTotalUnitCount:0];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_fetcher stopFetching];
|
||||
}
|
||||
|
||||
- (void)enqueue {
|
||||
[self enqueueWithData:nil];
|
||||
}
|
||||
|
||||
- (void)enqueueWithData:(nullable NSData *)resumeData {
|
||||
__weak FIRStorageDownloadTask *weakSelf = self;
|
||||
|
||||
[self dispatchAsync:^() {
|
||||
FIRStorageDownloadTask *strongSelf = weakSelf;
|
||||
|
||||
if (!strongSelf) {
|
||||
return;
|
||||
}
|
||||
|
||||
strongSelf.state = FIRStorageTaskStateQueueing;
|
||||
NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy];
|
||||
request.HTTPMethod = @"GET";
|
||||
request.timeoutInterval = strongSelf.reference.storage.maxDownloadRetryTime;
|
||||
NSURLComponents *components = [NSURLComponents componentsWithURL:request.URL
|
||||
resolvingAgainstBaseURL:NO];
|
||||
[components setQuery:@"alt=media"];
|
||||
request.URL = components.URL;
|
||||
|
||||
GTMSessionFetcher *fetcher;
|
||||
if (resumeData) {
|
||||
fetcher = [GTMSessionFetcher fetcherWithDownloadResumeData:resumeData];
|
||||
fetcher.comment = @"Resuming DownloadTask";
|
||||
} else {
|
||||
fetcher = [strongSelf.fetcherService fetcherWithRequest:request];
|
||||
fetcher.comment = @"Starting DownloadTask";
|
||||
}
|
||||
|
||||
[fetcher setResumeDataBlock:^(NSData *data) {
|
||||
FIRStorageDownloadTask *strong = weakSelf;
|
||||
if (strong && data) {
|
||||
strong->_downloadData = data;
|
||||
}
|
||||
}];
|
||||
|
||||
fetcher.maxRetryInterval = strongSelf.reference.storage.maxDownloadRetryInterval;
|
||||
|
||||
if (strongSelf->_fileURL) {
|
||||
// Handle file downloads
|
||||
[fetcher setDestinationFileURL:strongSelf->_fileURL];
|
||||
[fetcher setDownloadProgressBlock:^(int64_t bytesWritten, int64_t totalBytesWritten,
|
||||
int64_t totalBytesExpectedToWrite) {
|
||||
weakSelf.state = FIRStorageTaskStateProgress;
|
||||
weakSelf.progress.completedUnitCount = totalBytesWritten;
|
||||
weakSelf.progress.totalUnitCount = totalBytesExpectedToWrite;
|
||||
FIRStorageTaskSnapshot *snapshot = weakSelf.snapshot;
|
||||
[weakSelf fireHandlersForStatus:FIRStorageTaskStatusProgress snapshot:snapshot];
|
||||
weakSelf.state = FIRStorageTaskStateRunning;
|
||||
}];
|
||||
} else {
|
||||
// Handle data downloads
|
||||
[fetcher setReceivedProgressBlock:^(int64_t bytesWritten, int64_t totalBytesWritten) {
|
||||
weakSelf.state = FIRStorageTaskStateProgress;
|
||||
weakSelf.progress.completedUnitCount = totalBytesWritten;
|
||||
int64_t totalLength = [[weakSelf.fetcher response] expectedContentLength];
|
||||
weakSelf.progress.totalUnitCount = totalLength;
|
||||
FIRStorageTaskSnapshot *snapshot = weakSelf.snapshot;
|
||||
[weakSelf fireHandlersForStatus:FIRStorageTaskStatusProgress snapshot:snapshot];
|
||||
weakSelf.state = FIRStorageTaskStateRunning;
|
||||
}];
|
||||
}
|
||||
|
||||
strongSelf->_fetcher = fetcher;
|
||||
strongSelf->_fetcherCompletion = ^(NSData *data, NSError *error) {
|
||||
// Fire last progress updates
|
||||
[self fireHandlersForStatus:FIRStorageTaskStatusProgress snapshot:self.snapshot];
|
||||
|
||||
// Handle potential issues with download
|
||||
if (error) {
|
||||
self.state = FIRStorageTaskStateFailed;
|
||||
self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference];
|
||||
[self fireHandlersForStatus:FIRStorageTaskStatusFailure snapshot:self.snapshot];
|
||||
[self removeAllObservers];
|
||||
self->_fetcherCompletion = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
// Download completed successfully, fire completion callbacks
|
||||
self.state = FIRStorageTaskStateSuccess;
|
||||
|
||||
if (data) {
|
||||
self->_downloadData = data;
|
||||
}
|
||||
|
||||
[self fireHandlersForStatus:FIRStorageTaskStatusSuccess snapshot:self.snapshot];
|
||||
[self removeAllObservers];
|
||||
self->_fetcherCompletion = nil;
|
||||
};
|
||||
|
||||
strongSelf.state = FIRStorageTaskStateRunning;
|
||||
[strongSelf.fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) {
|
||||
FIRStorageDownloadTask *strongSelf = weakSelf;
|
||||
if (strongSelf.fetcherCompletion) {
|
||||
strongSelf.fetcherCompletion(data, error);
|
||||
}
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Download Management
|
||||
|
||||
- (void)cancel {
|
||||
NSError *error = [FIRStorageErrors errorWithCode:FIRStorageErrorCodeCancelled];
|
||||
[self cancelWithError:error];
|
||||
}
|
||||
|
||||
- (void)cancelWithError:(NSError *)error {
|
||||
__weak FIRStorageDownloadTask *weakSelf = self;
|
||||
[self dispatchAsync:^() {
|
||||
weakSelf.state = FIRStorageTaskStateCancelled;
|
||||
[weakSelf.fetcher stopFetching];
|
||||
weakSelf.error = error;
|
||||
[weakSelf fireHandlersForStatus:FIRStorageTaskStatusFailure snapshot:weakSelf.snapshot];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)pause {
|
||||
__weak FIRStorageDownloadTask *weakSelf = self;
|
||||
[self dispatchAsync:^() {
|
||||
__strong FIRStorageDownloadTask *strongSelf = weakSelf;
|
||||
if (!strongSelf || strongSelf.state == FIRStorageTaskStatePaused ||
|
||||
strongSelf.state == FIRStorageTaskStatePausing) {
|
||||
return;
|
||||
}
|
||||
strongSelf.state = FIRStorageTaskStatePausing;
|
||||
// Use the resume callback to confirm pause status since it always runs after the last
|
||||
// NSURLSession update.
|
||||
[strongSelf.fetcher setResumeDataBlock:^(NSData *data) {
|
||||
// Silence compiler warning about retain cycles
|
||||
__strong __typeof(self) strong = weakSelf;
|
||||
strong->_downloadData = data;
|
||||
strong.state = FIRStorageTaskStatePaused;
|
||||
FIRStorageTaskSnapshot *snapshot = strong.snapshot;
|
||||
[strong fireHandlersForStatus:FIRStorageTaskStatusPause snapshot:snapshot];
|
||||
}];
|
||||
[strongSelf.fetcher stopFetching];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)resume {
|
||||
__weak FIRStorageDownloadTask *weakSelf = self;
|
||||
[self dispatchAsync:^() {
|
||||
weakSelf.state = FIRStorageTaskStateResuming;
|
||||
FIRStorageTaskSnapshot *snapshot = weakSelf.snapshot;
|
||||
[weakSelf fireHandlersForStatus:FIRStorageTaskStatusResume snapshot:snapshot];
|
||||
weakSelf.state = FIRStorageTaskStateRunning;
|
||||
[weakSelf enqueueWithData:weakSelf.downloadData];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageDownloadTask.h"
|
||||
|
||||
@class FIRStorageReference;
|
||||
@class GTMSessionFetcherService;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FIRStorageDownloadTask ()
|
||||
|
||||
/**
|
||||
* Bytes which have been downloaded so far.
|
||||
*/
|
||||
@property(readonly, nonatomic) NSData *downloadData;
|
||||
|
||||
/**
|
||||
* The file on disk to write to.
|
||||
*/
|
||||
@property(copy, nonatomic) NSURL *fileURL;
|
||||
|
||||
/**
|
||||
* Initializes a download task with a base FIRStorageReference and GTMSessionFetcherService.
|
||||
* @param reference The base FIRStorageReference which fetchers use for configuration.
|
||||
* @param service The GTMSessionFetcherService which will create fetchers.
|
||||
* @param queue The shared queue to use for all Storage operations.
|
||||
* @param fileURL The system URL to download to. If nil, download in memory as bytes.
|
||||
* @return Returns an instance of FIRStorageDownloadTask
|
||||
*/
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue
|
||||
file:(nullable NSURL *)fileURL;
|
||||
|
||||
/**
|
||||
* Cancels the download task and passes an appropriate error to the developer.
|
||||
* @param error NSError to propegate to the developer.
|
||||
*/
|
||||
- (void)cancelWithError:(NSError *)error;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageConstants.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class FIRStorageReference;
|
||||
|
||||
/**
|
||||
* Adds wrappers for common Firebase Storage errors (including creating errors from GCS errors).
|
||||
* For more information on unwrapping GCS errors, see the GCS errors docs:
|
||||
* https://cloud.google.com/storage/docs/json_api/v1/status-codes
|
||||
* This is never publicly exposed to end developers (as they will simply see an NSError).
|
||||
*/
|
||||
@interface FIRStorageErrors : NSObject
|
||||
|
||||
/**
|
||||
* Creates a Firebase Storage error from a specific FIRStorageErrorCode.
|
||||
*/
|
||||
+ (NSError *)errorWithCode:(FIRStorageErrorCode)code;
|
||||
|
||||
/**
|
||||
* Creates a Firebase Storage error from a specific FIRStorageErrorCode while adding
|
||||
* custom info from an optionally provided info dictionary.
|
||||
*/
|
||||
+ (NSError *)errorWithCode:(FIRStorageErrorCode)code
|
||||
infoDictionary:(nullable NSDictionary *)dictionary;
|
||||
|
||||
/**
|
||||
* 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 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
|
||||
@@ -0,0 +1,190 @@
|
||||
// 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 "FirebaseStorage/Sources/FIRStorageErrors.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageReference.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageReference_Private.h"
|
||||
|
||||
@implementation FIRStorageErrors
|
||||
|
||||
+ (NSError *)errorWithCode:(FIRStorageErrorCode)code {
|
||||
return [FIRStorageErrors errorWithCode:code infoDictionary:nil];
|
||||
}
|
||||
|
||||
+ (NSError *)errorWithCode:(FIRStorageErrorCode)code
|
||||
infoDictionary:(nullable NSDictionary *)dictionary {
|
||||
NSMutableDictionary *errorDictionary;
|
||||
if (dictionary) {
|
||||
errorDictionary = [dictionary mutableCopy];
|
||||
} else {
|
||||
errorDictionary = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
|
||||
NSString *errorMessage;
|
||||
switch (code) {
|
||||
case FIRStorageErrorCodeObjectNotFound:
|
||||
errorMessage =
|
||||
[NSString stringWithFormat:@"Object %@ does not exist.", errorDictionary[@"object"]];
|
||||
break;
|
||||
|
||||
case FIRStorageErrorCodeBucketNotFound:
|
||||
errorMessage =
|
||||
[NSString stringWithFormat:@"Bucket %@ does not exist.", errorDictionary[@"bucket"]];
|
||||
break;
|
||||
|
||||
case FIRStorageErrorCodeProjectNotFound:
|
||||
errorMessage =
|
||||
[NSString stringWithFormat:@"Project %@ does not exist.", errorDictionary[@"project"]];
|
||||
break;
|
||||
|
||||
case FIRStorageErrorCodeQuotaExceeded: {
|
||||
NSString *const kQuotaExceededFormat =
|
||||
@"Quota for bucket %@ exceeded, please view quota on firebase.google.com.";
|
||||
errorMessage = [NSString stringWithFormat:kQuotaExceededFormat, errorDictionary[@"bucket"]];
|
||||
break;
|
||||
}
|
||||
|
||||
case FIRStorageErrorCodeDownloadSizeExceeded: {
|
||||
int64_t total = [errorDictionary[@"totalSize"] longLongValue];
|
||||
int64_t size = [errorDictionary[@"maxAllowedSize"] longLongValue];
|
||||
NSString *totalString = total ? @(total).stringValue : @"unknown";
|
||||
NSString *sizeString = total ? @(size).stringValue : @"unknown";
|
||||
NSString *const kSizeExceededErrorFormat =
|
||||
@"Attempted to download object with size of %@ bytes, "
|
||||
@"which exceeds the maximum size of %@ bytes. "
|
||||
@"Consider raising the maximum download size, or using "
|
||||
@"[FIRStorageReference writeToFile:]";
|
||||
errorMessage = [NSString stringWithFormat:kSizeExceededErrorFormat, totalString, sizeString];
|
||||
break;
|
||||
}
|
||||
|
||||
case FIRStorageErrorCodeUnauthenticated:
|
||||
errorMessage = @"User is not authenticated, please authenticate using Firebase "
|
||||
@"Authentication and try again.";
|
||||
break;
|
||||
|
||||
case FIRStorageErrorCodeUnauthorized: {
|
||||
NSString *bucket = errorDictionary[@"bucket"];
|
||||
NSString *object = errorDictionary[@"object"];
|
||||
NSString *const kUnauthorizedFormat = @"User does not have permission to access gs://%@/%@.";
|
||||
errorMessage = [NSString stringWithFormat:kUnauthorizedFormat, bucket, object];
|
||||
break;
|
||||
}
|
||||
|
||||
case FIRStorageErrorCodeRetryLimitExceeded:
|
||||
errorMessage = @"Max retry time for operation exceeded, please try again.";
|
||||
break;
|
||||
|
||||
case FIRStorageErrorCodeNonMatchingChecksum: {
|
||||
// TODO: replace with actual checksum strings when we choose to implement.
|
||||
NSString *const kChecksumFailedErrorFormat =
|
||||
@"Uploaded/downloaded object %@ has checksum: %@ "
|
||||
@"which does not match server checksum: %@. Please retry the upload/download.";
|
||||
errorMessage = [NSString stringWithFormat:kChecksumFailedErrorFormat, @"object",
|
||||
@"client checksum", @"server checksum"];
|
||||
break;
|
||||
}
|
||||
|
||||
case FIRStorageErrorCodeCancelled:
|
||||
errorMessage = @"User cancelled the upload/download.";
|
||||
break;
|
||||
|
||||
case FIRStorageErrorCodeUnknown:
|
||||
/* Fall through to default case for unknown errors */
|
||||
|
||||
default:
|
||||
errorMessage = @"An unknown error occurred, please check the server response.";
|
||||
break;
|
||||
}
|
||||
|
||||
errorDictionary[NSLocalizedDescriptionKey] = errorMessage;
|
||||
|
||||
NSError *err = [NSError errorWithDomain:FIRStorageErrorDomain code:code userInfo:errorDictionary];
|
||||
return err;
|
||||
}
|
||||
|
||||
+ (nullable NSError *)errorWithServerError:(nullable NSError *)error
|
||||
reference:(nullable FIRStorageReference *)reference {
|
||||
if (error == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
FIRStorageErrorCode errorCode;
|
||||
switch (error.code) {
|
||||
case 400:
|
||||
errorCode = FIRStorageErrorCodeUnknown;
|
||||
break;
|
||||
|
||||
case 401:
|
||||
errorCode = FIRStorageErrorCodeUnauthenticated;
|
||||
break;
|
||||
|
||||
case 402:
|
||||
errorCode = FIRStorageErrorCodeQuotaExceeded;
|
||||
break;
|
||||
|
||||
case 403:
|
||||
errorCode = FIRStorageErrorCodeUnauthorized;
|
||||
break;
|
||||
|
||||
case 404:
|
||||
errorCode = FIRStorageErrorCodeObjectNotFound;
|
||||
break;
|
||||
|
||||
default:
|
||||
errorCode = FIRStorageErrorCodeUnknown;
|
||||
break;
|
||||
}
|
||||
|
||||
NSMutableDictionary *errorDictionary =
|
||||
[[[NSDictionary alloc] initWithDictionary:error.userInfo] mutableCopy];
|
||||
errorDictionary[kFIRStorageResponseErrorDomain] = error.domain;
|
||||
errorDictionary[kFIRStorageResponseErrorCode] = @(error.code);
|
||||
|
||||
// Turn raw response into a string
|
||||
NSData *responseData = errorDictionary[@"data"];
|
||||
if (responseData) {
|
||||
NSString *errorString = [[NSString alloc] initWithData:responseData
|
||||
encoding:NSUTF8StringEncoding];
|
||||
errorDictionary[kFIRStorageResponseBody] = errorString ?: @"No Response from Server.";
|
||||
}
|
||||
|
||||
errorDictionary[@"bucket"] = reference.path.bucket;
|
||||
errorDictionary[@"object"] = reference.path.object;
|
||||
|
||||
NSError *clientError = [FIRStorageErrors errorWithCode:errorCode infoDictionary:errorDictionary];
|
||||
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
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 "FirebaseStorage/Sources/Public/FirebaseStorage/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
|
||||
dispatchQueue:(dispatch_queue_t)queue
|
||||
completion:(FIRStorageVoidURLError)completion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
// 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 "FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageTask_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorage_Private.h"
|
||||
|
||||
@implementation FIRStorageGetDownloadURLTask {
|
||||
@private
|
||||
FIRStorageVoidURLError _completion;
|
||||
}
|
||||
|
||||
@synthesize fetcher = _fetcher;
|
||||
@synthesize fetcherCompletion = _fetcherCompletion;
|
||||
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue
|
||||
completion:(FIRStorageVoidURLError)completion {
|
||||
self = [super initWithReference:reference fetcherService:service dispatchQueue:queue];
|
||||
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 = self.reference.storage.scheme;
|
||||
components.host = self.reference.storage.host;
|
||||
components.port = self.reference.storage.port;
|
||||
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 {
|
||||
__weak FIRStorageGetDownloadURLTask *weakSelf = self;
|
||||
|
||||
[self dispatchAsync:^() {
|
||||
FIRStorageGetDownloadURLTask *strongSelf = weakSelf;
|
||||
if (!strongSelf) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy];
|
||||
request.HTTPMethod = @"GET";
|
||||
request.timeoutInterval = strongSelf.reference.storage.maxOperationRetryTime;
|
||||
|
||||
FIRStorageVoidURLError callback = strongSelf->_completion;
|
||||
strongSelf->_completion = nil;
|
||||
|
||||
GTMSessionFetcher *fetcher = [strongSelf.fetcherService fetcherWithRequest:request];
|
||||
strongSelf->_fetcher = fetcher;
|
||||
fetcher.comment = @"GetDownloadURLTask";
|
||||
|
||||
strongSelf->_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 = [strongSelf 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;
|
||||
};
|
||||
[fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) {
|
||||
FIRStorageGetDownloadURLTask *strongSelf = weakSelf;
|
||||
if (strongSelf.fetcherCompletion) {
|
||||
strongSelf.fetcherCompletion(data, error);
|
||||
}
|
||||
}];
|
||||
}];
|
||||
};
|
||||
|
||||
@end
|
||||
+31
@@ -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 "FirebaseStorage/Sources/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
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageTask.h"
|
||||
|
||||
@class GTMSessionFetcherService;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* Task which provides the ability to get metadata on an object in Firebase Storage.
|
||||
*/
|
||||
@interface FIRStorageGetMetadataTask : FIRStorageTask <FIRStorageTaskManagement>
|
||||
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue
|
||||
completion:(FIRStorageVoidMetadataError)completion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,98 @@
|
||||
// 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 "FirebaseStorage/Sources/FIRStorageGetMetadataTask.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageConstants.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageMetadata_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageTask_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageUtils.h"
|
||||
|
||||
@implementation FIRStorageGetMetadataTask {
|
||||
@private
|
||||
FIRStorageVoidMetadataError _completion;
|
||||
}
|
||||
|
||||
@synthesize fetcher = _fetcher;
|
||||
@synthesize fetcherCompletion = _fetcherCompletion;
|
||||
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue
|
||||
completion:(FIRStorageVoidMetadataError)completion {
|
||||
self = [super initWithReference:reference fetcherService:service dispatchQueue:queue];
|
||||
if (self) {
|
||||
_completion = [completion copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_fetcher stopFetching];
|
||||
}
|
||||
|
||||
- (void)enqueue {
|
||||
__weak FIRStorageGetMetadataTask *weakSelf = self;
|
||||
|
||||
[self dispatchAsync:^() {
|
||||
FIRStorageGetMetadataTask *strongSelf = weakSelf;
|
||||
|
||||
if (!strongSelf) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy];
|
||||
request.HTTPMethod = @"GET";
|
||||
request.timeoutInterval = strongSelf.reference.storage.maxOperationRetryTime;
|
||||
|
||||
FIRStorageVoidMetadataError callback = strongSelf->_completion;
|
||||
strongSelf->_completion = nil;
|
||||
|
||||
GTMSessionFetcher *fetcher = [strongSelf.fetcherService fetcherWithRequest:request];
|
||||
strongSelf->_fetcher = fetcher;
|
||||
fetcher.comment = @"GetMetadataTask";
|
||||
|
||||
strongSelf->_fetcherCompletion = ^(NSData *data, NSError *error) {
|
||||
FIRStorageMetadata *metadata;
|
||||
if (error) {
|
||||
if (!self.error) {
|
||||
self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference];
|
||||
}
|
||||
} else {
|
||||
NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data];
|
||||
if (responseDictionary != nil) {
|
||||
metadata = [[FIRStorageMetadata alloc] initWithDictionary:responseDictionary];
|
||||
[metadata setType:FIRStorageMetadataTypeFile];
|
||||
} else {
|
||||
self.error = [FIRStorageErrors errorWithInvalidRequest:data];
|
||||
}
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback(metadata, self.error);
|
||||
}
|
||||
self->_fetcherCompletion = nil;
|
||||
};
|
||||
|
||||
[fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) {
|
||||
FIRStorageGetMetadataTask *strongSelf = weakSelf;
|
||||
if (strongSelf.fetcherCompletion) {
|
||||
strongSelf.fetcherCompletion(data, error);
|
||||
}
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright 2019 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageListResult.h"
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageReference.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h"
|
||||
|
||||
@implementation FIRStorageListResult
|
||||
|
||||
+ (nullable FIRStorageListResult *)fromDictionary:(NSDictionary<NSString *, id> *)dictionary
|
||||
atReference:(FIRStorageReference *)reference {
|
||||
NSMutableArray<FIRStorageReference *> *prefixes = [NSMutableArray new];
|
||||
NSMutableArray<FIRStorageReference *> *items = [NSMutableArray new];
|
||||
|
||||
FIRStorageReference *rootReference = reference.root;
|
||||
|
||||
NSArray<NSString *> *prefixEntries = dictionary[kFIRStorageListPrefixes];
|
||||
for (NSString *prefixEntry in prefixEntries) {
|
||||
NSString *pathWithoutTrailingSlash = prefixEntry;
|
||||
if ([prefixEntry hasSuffix:@"/"]) {
|
||||
pathWithoutTrailingSlash = [pathWithoutTrailingSlash substringToIndex:prefixEntry.length - 1];
|
||||
}
|
||||
|
||||
FIRStorageReference *prefixReference = [rootReference child:pathWithoutTrailingSlash];
|
||||
[prefixes addObject:prefixReference];
|
||||
}
|
||||
|
||||
NSArray<NSDictionary<NSString *, NSString *> *> *itemEntries = dictionary[kFIRStorageListItems];
|
||||
for (NSDictionary<NSString *, NSString *> *itemEntry in itemEntries) {
|
||||
FIRStorageReference *itemReference = [rootReference child:itemEntry[kFIRStorageListItemName]];
|
||||
[items addObject:itemReference];
|
||||
}
|
||||
|
||||
NSString *pageToken = dictionary[kFIRStorageListPageToken];
|
||||
return [[FIRStorageListResult alloc] initWithPrefixes:prefixes items:items pageToken:pageToken];
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithPrefixes:(NSArray<FIRStorageReference *> *)prefixes
|
||||
items:(NSArray<FIRStorageReference *> *)items
|
||||
pageToken:(nullable NSString *)pageToken {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_prefixes = [prefixes copy];
|
||||
_items = [items copy];
|
||||
_pageToken = [pageToken copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)copyWithZone:(NSZone *)zone {
|
||||
FIRStorageListResult *clone = [[[self class] allocWithZone:zone] initWithPrefixes:_prefixes
|
||||
items:_items
|
||||
pageToken:_pageToken];
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2019 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageListResult.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FIRStorageListResult (Private)
|
||||
|
||||
/**
|
||||
* Creates an instance of FIRStorageListResult with the contents of a dictionary.
|
||||
*
|
||||
* @param dictionary A dictionary containing the parsed JSON response from the backend.
|
||||
* @param reference The FIRStorageReference that `list()` was called on.
|
||||
* @return An instance of FIRStorageListResult that represents the contents of the dictionary.
|
||||
*/
|
||||
+ (nullable FIRStorageListResult *)fromDictionary:(NSDictionary<NSString *, id> *)dictionary
|
||||
atReference:(FIRStorageReference *)reference;
|
||||
|
||||
/** Initializes a new FIRStorageListResult with the given data. */
|
||||
- (nullable instancetype)initWithPrefixes:(NSArray<FIRStorageReference *> *)prefixes
|
||||
items:(NSArray<FIRStorageReference *> *)items
|
||||
pageToken:(nullable NSString *)pageToken;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2019 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageListResult.h"
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageTask.h"
|
||||
|
||||
@class GTMSessionFetcherService;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* Block typedef typically used in `list()` and `listAll()`.
|
||||
* @param listResult The FIRStorageListResult returned by the operation, if it exists.
|
||||
* @param error The error describing failure, if one occurred.
|
||||
*/
|
||||
typedef void (^FIRStorageVoidListError)(FIRStorageListResult *_Nullable listResult,
|
||||
NSError *_Nullable error);
|
||||
|
||||
/** A Task that lists the entries under a {@link StorageReference} */
|
||||
@interface FIRStorageListTask : FIRStorageTask <FIRStorageTaskManagement>
|
||||
|
||||
/**
|
||||
* Initializes a new List Task.
|
||||
*
|
||||
* To schedule the task, invoke `[FIRStorageListTask enqueue]`.
|
||||
*
|
||||
* @param reference The location to invoke List on.
|
||||
* @param service GTMSessionFetcherService to use for the RPC.
|
||||
* @param queue The queue to schedule the List operation on.
|
||||
* @param pageSize An optional pageSize, denoting the maximum size of the result set. If
|
||||
* set to `nil`, the backend will use the default page size.
|
||||
* @param previousPageToken An optional pageToken, used to resume a previous invocation.
|
||||
* @param completion The completion handler to be called with the FIRStorageListResult.
|
||||
*/
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue
|
||||
pageSize:(nullable NSNumber *)pageSize
|
||||
previousPageToken:(nullable NSString *)previousPageToken
|
||||
completion:(FIRStorageVoidListError)completion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,126 @@
|
||||
// Copyright 2019 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 "FirebaseStorage/Sources/FIRStorageListTask.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageListResult_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageReference_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageTask_Private.h"
|
||||
|
||||
@implementation FIRStorageListTask {
|
||||
@private
|
||||
FIRStorageVoidListError _completion;
|
||||
NSNumber *_pageSize;
|
||||
NSString *_previousPageToken;
|
||||
}
|
||||
|
||||
@synthesize fetcher = _fetcher;
|
||||
@synthesize fetcherCompletion = _fetcherCompletion;
|
||||
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue
|
||||
pageSize:(nullable NSNumber *)pageSize
|
||||
previousPageToken:(nullable NSString *)previousPageToken
|
||||
completion:(FIRStorageVoidListError)completion {
|
||||
self = [super initWithReference:reference fetcherService:service dispatchQueue:queue];
|
||||
if (self) {
|
||||
_completion = [completion copy];
|
||||
_pageSize = pageSize;
|
||||
_previousPageToken = [previousPageToken copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_fetcher stopFetching];
|
||||
}
|
||||
|
||||
- (void)enqueue {
|
||||
__weak FIRStorageListTask *weakSelf = self;
|
||||
|
||||
[self dispatchAsync:^() {
|
||||
FIRStorageListTask *strongSelf = weakSelf;
|
||||
|
||||
if (!strongSelf) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableDictionary<NSString *, NSString *> *queryParams = [NSMutableDictionary new];
|
||||
|
||||
NSString *prefix = [self reference].fullPath;
|
||||
if (prefix.length != 0) {
|
||||
queryParams[@"prefix"] = [prefix stringByAppendingString:@"/"];
|
||||
}
|
||||
|
||||
// Firebase Storage uses file system semantics and treats slashes as separators. GCS's List API
|
||||
// does not prescribe a separator, and hence we need to provide a slash as the delimiter.
|
||||
queryParams[@"delimiter"] = @"/";
|
||||
|
||||
// listAll() doesn't set a pageSize as this allows Firebase Storage to determine how many items
|
||||
// to return per page. This removes the need to backfill results if Firebase Storage filters
|
||||
// objects that are considered invalid (such as items with two consecutive slashes).
|
||||
if (strongSelf->_pageSize != nil) {
|
||||
queryParams[@"maxResults"] = [strongSelf->_pageSize stringValue];
|
||||
}
|
||||
|
||||
if (strongSelf->_previousPageToken) {
|
||||
queryParams[@"pageToken"] = strongSelf->_previousPageToken;
|
||||
}
|
||||
|
||||
FIRStorageReference *root = self.reference.root;
|
||||
NSMutableURLRequest *request =
|
||||
[[FIRStorageUtils defaultRequestForReference:root queryParams:queryParams] mutableCopy];
|
||||
|
||||
request.HTTPMethod = @"GET";
|
||||
request.timeoutInterval = strongSelf.reference.storage.maxOperationRetryTime;
|
||||
|
||||
FIRStorageVoidListError callback = strongSelf->_completion;
|
||||
strongSelf->_completion = nil;
|
||||
|
||||
GTMSessionFetcher *fetcher = [strongSelf.fetcherService fetcherWithRequest:request];
|
||||
strongSelf->_fetcher = fetcher;
|
||||
fetcher.comment = @"ListTask";
|
||||
|
||||
strongSelf->_fetcherCompletion = ^(NSData *data, NSError *error) {
|
||||
FIRStorageListResult *listResult;
|
||||
if (error) {
|
||||
self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference];
|
||||
} else {
|
||||
NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data];
|
||||
if (responseDictionary != nil) {
|
||||
listResult = [FIRStorageListResult fromDictionary:responseDictionary
|
||||
atReference:self.reference];
|
||||
} else {
|
||||
self.error = [FIRStorageErrors errorWithInvalidRequest:data];
|
||||
}
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback(listResult, self.error);
|
||||
}
|
||||
|
||||
// Remove retain cycle set up by `strongSelf->_fetcherCompletion`
|
||||
self->_fetcherCompletion = nil;
|
||||
};
|
||||
|
||||
[fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) {
|
||||
FIRStorageListTask *strongSelf = weakSelf;
|
||||
if (strongSelf.fetcherCompletion) {
|
||||
strongSelf.fetcherCompletion(data, error);
|
||||
}
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"
|
||||
|
||||
extern FIRLoggerService kFIRLoggerStorage;
|
||||
|
||||
// FIRStorageTokenAuthorizer.m
|
||||
extern NSString *const kFIRStorageMessageCodeAppCheckError;
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* 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 "FirebaseStorage/Sources/FIRStorageLogger.h"
|
||||
|
||||
FIRLoggerService kFIRLoggerStorage = @"[Firebase/Storage]";
|
||||
|
||||
// FIRStorageTokenAuthorizer.m
|
||||
NSString *const kFIRStorageMessageCodeAppCheckError = @"I-STR000001";
|
||||
@@ -0,0 +1,225 @@
|
||||
// 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageMetadata.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageConstants.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageMetadata_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageUtils.h"
|
||||
|
||||
// TODO: consider rewriting this using GTLR (GTLRStorageObjects.h)
|
||||
@implementation FIRStorageMetadata
|
||||
|
||||
#pragma mark - Initializers
|
||||
|
||||
- (instancetype)init {
|
||||
return [self initWithDictionary:[NSDictionary dictionary]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_initialMetadata = [dictionary copy];
|
||||
|
||||
_bucket = dictionary[kFIRStorageMetadataBucket];
|
||||
_cacheControl = dictionary[kFIRStorageMetadataCacheControl];
|
||||
_contentDisposition = dictionary[kFIRStorageMetadataContentDisposition];
|
||||
_contentEncoding = dictionary[kFIRStorageMetadataContentEncoding];
|
||||
_contentLanguage = dictionary[kFIRStorageMetadataContentLanguage];
|
||||
_contentType = dictionary[kFIRStorageMetadataContentType];
|
||||
_customMetadata = dictionary[kFIRStorageMetadataCustomMetadata];
|
||||
_size = [dictionary[kFIRStorageMetadataSize] longLongValue];
|
||||
_generation = [dictionary[kFIRStorageMetadataGeneration] longLongValue];
|
||||
_metageneration = [dictionary[kFIRStorageMetadataMetageneration] longLongValue];
|
||||
_timeCreated = [self dateFromRFC3339String:dictionary[kFIRStorageMetadataTimeCreated]];
|
||||
_updated = [self dateFromRFC3339String:dictionary[kFIRStorageMetadataUpdated]];
|
||||
_md5Hash = dictionary[kFIRStorageMetadataMd5Hash];
|
||||
// GCS "name" is our path, our "name" is just the last path component of the path
|
||||
_path = dictionary[kFIRStorageMetadataName];
|
||||
_name = [_path lastPathComponent];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - NSObject overrides
|
||||
|
||||
- (instancetype)copyWithZone:(NSZone *)zone {
|
||||
FIRStorageMetadata *clone =
|
||||
[[[self class] allocWithZone:zone] initWithDictionary:[self dictionaryRepresentation]];
|
||||
clone.initialMetadata = [self.initialMetadata copy];
|
||||
return clone;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object {
|
||||
if (self == object) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (![object isKindOfClass:[FIRStorageMetadata class]]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
BOOL isEqualObject = [self isEqualToFIRStorageMetadata:(FIRStorageMetadata *)object];
|
||||
return isEqualObject;
|
||||
}
|
||||
|
||||
- (BOOL)isEqualToFIRStorageMetadata:(FIRStorageMetadata *)metadata {
|
||||
return [[self dictionaryRepresentation] isEqualToDictionary:[metadata dictionaryRepresentation]];
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
NSUInteger hash = [[self dictionaryRepresentation] hash];
|
||||
return hash;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
NSDictionary *metadataDictionary = [self dictionaryRepresentation];
|
||||
return [NSString stringWithFormat:@"%@ %p: %@", [self class], self, metadataDictionary];
|
||||
}
|
||||
|
||||
#pragma mark - Public methods
|
||||
|
||||
- (NSDictionary *)dictionaryRepresentation {
|
||||
NSMutableDictionary *metadataDictionary = [[NSMutableDictionary alloc] initWithCapacity:13];
|
||||
|
||||
if (_bucket) {
|
||||
metadataDictionary[kFIRStorageMetadataBucket] = _bucket;
|
||||
}
|
||||
|
||||
if (_cacheControl) {
|
||||
metadataDictionary[kFIRStorageMetadataCacheControl] = _cacheControl;
|
||||
}
|
||||
|
||||
if (_contentDisposition) {
|
||||
metadataDictionary[kFIRStorageMetadataContentDisposition] = _contentDisposition;
|
||||
}
|
||||
|
||||
if (_contentEncoding) {
|
||||
metadataDictionary[kFIRStorageMetadataContentEncoding] = _contentEncoding;
|
||||
}
|
||||
|
||||
if (_contentLanguage) {
|
||||
metadataDictionary[kFIRStorageMetadataContentLanguage] = _contentLanguage;
|
||||
}
|
||||
|
||||
if (_contentType) {
|
||||
metadataDictionary[kFIRStorageMetadataContentType] = _contentType;
|
||||
}
|
||||
|
||||
if (_md5Hash) {
|
||||
metadataDictionary[kFIRStorageMetadataMd5Hash] = _md5Hash;
|
||||
}
|
||||
|
||||
if (_customMetadata) {
|
||||
metadataDictionary[kFIRStorageMetadataCustomMetadata] = _customMetadata;
|
||||
}
|
||||
|
||||
if (_generation) {
|
||||
NSString *generationString = [NSString stringWithFormat:@"%lld", _generation];
|
||||
metadataDictionary[kFIRStorageMetadataGeneration] = generationString;
|
||||
}
|
||||
|
||||
if (_metageneration) {
|
||||
NSString *metagenerationString = [NSString stringWithFormat:@"%lld", _metageneration];
|
||||
metadataDictionary[kFIRStorageMetadataMetageneration] = metagenerationString;
|
||||
}
|
||||
|
||||
if (_timeCreated) {
|
||||
metadataDictionary[kFIRStorageMetadataTimeCreated] = [self RFC3339StringFromDate:_timeCreated];
|
||||
}
|
||||
|
||||
if (_updated) {
|
||||
metadataDictionary[kFIRStorageMetadataUpdated] = [self RFC3339StringFromDate:_updated];
|
||||
}
|
||||
|
||||
if (_path) {
|
||||
metadataDictionary[kFIRStorageMetadataName] = _path;
|
||||
}
|
||||
|
||||
if (_size) {
|
||||
metadataDictionary[kFIRStorageMetadataSize] = [NSNumber numberWithLongLong:_size];
|
||||
}
|
||||
|
||||
return [metadataDictionary copy];
|
||||
}
|
||||
|
||||
- (BOOL)isFile {
|
||||
return _type == FIRStorageMetadataTypeFile;
|
||||
}
|
||||
|
||||
- (BOOL)isFolder {
|
||||
return _type == FIRStorageMetadataTypeFolder;
|
||||
}
|
||||
|
||||
#pragma mark - Private methods
|
||||
|
||||
+ (void)removeMatchingMetadata:(NSMutableDictionary *)metadata
|
||||
oldMetadata:(NSDictionary *)oldMetadata {
|
||||
for (NSString *metadataKey in [oldMetadata allKeys]) {
|
||||
id oldValue = [oldMetadata objectForKey:metadataKey];
|
||||
id newValue = [metadata objectForKey:metadataKey];
|
||||
|
||||
if (oldValue && !newValue) {
|
||||
[metadata setObject:[NSNull null] forKey:metadataKey];
|
||||
} else if ([oldValue isKindOfClass:[NSString class]] &&
|
||||
[newValue isKindOfClass:[NSString class]]) {
|
||||
if ([oldValue isEqualToString:newValue]) {
|
||||
[metadata removeObjectForKey:metadataKey];
|
||||
}
|
||||
} else if ([oldValue isKindOfClass:[NSDictionary class]] &&
|
||||
[newValue isKindOfClass:[NSDictionary class]]) {
|
||||
NSMutableDictionary *nestedMetadata = [newValue mutableCopy];
|
||||
[self removeMatchingMetadata:nestedMetadata oldMetadata:oldValue];
|
||||
[metadata setObject:[nestedMetadata copy] forKey:metadataKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDictionary *)updatedMetadata {
|
||||
NSMutableDictionary *metadataUpdate = [[self dictionaryRepresentation] mutableCopy];
|
||||
[FIRStorageMetadata removeMatchingMetadata:metadataUpdate oldMetadata:_initialMetadata];
|
||||
return [metadataUpdate copy];
|
||||
}
|
||||
|
||||
#pragma mark - RFC 3339 conversions
|
||||
|
||||
static NSDateFormatter *sRFC3339DateFormatter;
|
||||
|
||||
static void setupDateFormatterOnce(void) {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sRFC3339DateFormatter = [[NSDateFormatter alloc] init];
|
||||
NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
|
||||
|
||||
[sRFC3339DateFormatter setLocale:enUSPOSIXLocale];
|
||||
[sRFC3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSZZZZZ"];
|
||||
[sRFC3339DateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
|
||||
});
|
||||
}
|
||||
|
||||
- (nullable NSDate *)dateFromRFC3339String:(NSString *)dateString {
|
||||
setupDateFormatterOnce();
|
||||
NSDate *rfc3339Date = [sRFC3339DateFormatter dateFromString:dateString];
|
||||
return rfc3339Date;
|
||||
}
|
||||
|
||||
- (nullable NSString *)RFC3339StringFromDate:(NSDate *)date {
|
||||
setupDateFormatterOnce();
|
||||
NSString *rfc3339String = [sRFC3339DateFormatter stringFromDate:date];
|
||||
return rfc3339String;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageMetadata.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h"
|
||||
|
||||
@class FIRStorageReference;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FIRStorageMetadata ()
|
||||
|
||||
@property(readwrite, nonatomic) NSString *name;
|
||||
|
||||
@property(readwrite, nonatomic) NSString *path;
|
||||
|
||||
@property(readwrite, nonatomic) FIRStorageReference *reference;
|
||||
|
||||
/**
|
||||
* The type of the object, either a "File" or a "Folder".
|
||||
*/
|
||||
@property(readwrite) FIRStorageMetadataType type;
|
||||
|
||||
/**
|
||||
* The original metadata representation received from the server or an empty dictionary
|
||||
* if the metadata object was initialized by the user.
|
||||
*/
|
||||
@property(copy, nonatomic) NSDictionary *initialMetadata;
|
||||
|
||||
/**
|
||||
* Recursively removes entries in 'metadata' that are unmodified from 'oldMetadata'.
|
||||
* Adds 'NSNull' for entries that only exist in oldMetadata.
|
||||
*/
|
||||
+ (void)removeMatchingMetadata:(NSMutableDictionary *)metadata
|
||||
oldMetadata:(NSDictionary *)oldMetadata;
|
||||
|
||||
/**
|
||||
* Computes the updates between the state at initialization and the current state.
|
||||
* Returns a dictionary with only the updated data. Removed keys are set to NSNull.
|
||||
*/
|
||||
- (NSDictionary *)updatedMetadata;
|
||||
|
||||
/**
|
||||
* Returns an RFC3339 formatted date from a string.
|
||||
* @param dateString An NSString of the form: yyyy-MM-ddTHH:mm:ss.SSSZ.
|
||||
* @return An NSDate populated from the string or nil if conversion isn't possible.
|
||||
*/
|
||||
- (nullable NSDate *)dateFromRFC3339String:(NSString *)dateString;
|
||||
|
||||
/**
|
||||
* Returns an RFC3339 formatted string from an NSDate object.
|
||||
* @param date The NSDate object to be converted to a string.
|
||||
* @return An NSString of the form: yyyy-MM-ddTHH:mm:ss.SSSZ or nil if conversion isn't possible.
|
||||
*/
|
||||
- (nullable NSString *)RFC3339StringFromDate:(NSDate *)date;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,215 @@
|
||||
// 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageObservableTask.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageObservableTask_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageTask_Private.h"
|
||||
|
||||
@implementation FIRStorageObservableTask {
|
||||
@private
|
||||
// Handlers for pause, resume, progress, success, and failure callbacks
|
||||
NSMutableDictionary<NSString *, FIRStorageVoidSnapshot> *_resumeHandlers;
|
||||
NSMutableDictionary<NSString *, FIRStorageVoidSnapshot> *_pauseHandlers;
|
||||
NSMutableDictionary<NSString *, FIRStorageVoidSnapshot> *_progressHandlers;
|
||||
NSMutableDictionary<NSString *, FIRStorageVoidSnapshot> *_successHandlers;
|
||||
NSMutableDictionary<NSString *, FIRStorageVoidSnapshot> *_failureHandlers;
|
||||
// Reverse map of fetcher handles to status types
|
||||
NSMutableDictionary<NSString *, NSNumber *> *_handleToStatusMap;
|
||||
}
|
||||
|
||||
@synthesize state = _state;
|
||||
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue {
|
||||
self = [super initWithReference:reference fetcherService:service dispatchQueue:queue];
|
||||
if (self) {
|
||||
_pauseHandlers = [[NSMutableDictionary alloc] init];
|
||||
_resumeHandlers = [[NSMutableDictionary alloc] init];
|
||||
_progressHandlers = [[NSMutableDictionary alloc] init];
|
||||
_successHandlers = [[NSMutableDictionary alloc] init];
|
||||
_failureHandlers = [[NSMutableDictionary alloc] init];
|
||||
_handleToStatusMap = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Observers
|
||||
|
||||
- (FIRStorageHandle)observeStatus:(FIRStorageTaskStatus)status
|
||||
handler:(FIRStorageVoidSnapshot)handler {
|
||||
FIRStorageVoidSnapshot callback = handler;
|
||||
|
||||
// Note: self.snapshot is synchronized
|
||||
FIRStorageTaskSnapshot *snapshot = self.snapshot;
|
||||
// TODO: use an increasing counter instead of a random UUID
|
||||
NSString *UUIDString = [[NSUUID UUID] UUIDString];
|
||||
switch (status) {
|
||||
case FIRStorageTaskStatusPause:
|
||||
@synchronized(self) {
|
||||
[_pauseHandlers setValue:callback forKey:UUIDString];
|
||||
} // @synchronized(self)
|
||||
if (_state == FIRStorageTaskStatePausing || _state == FIRStorageTaskStatePaused) {
|
||||
[self fireHandlers:_pauseHandlers snapshot:snapshot];
|
||||
}
|
||||
break;
|
||||
|
||||
case FIRStorageTaskStatusResume:
|
||||
@synchronized(self) {
|
||||
[_resumeHandlers setValue:callback forKey:UUIDString];
|
||||
} // @synchronized(self)
|
||||
if (_state == FIRStorageTaskStateResuming || _state == FIRStorageTaskStateRunning) {
|
||||
[self fireHandlers:_resumeHandlers snapshot:snapshot];
|
||||
}
|
||||
break;
|
||||
|
||||
case FIRStorageTaskStatusProgress:
|
||||
@synchronized(self) {
|
||||
[_progressHandlers setValue:callback forKey:UUIDString];
|
||||
} // @synchronized(self)
|
||||
if (_state == FIRStorageTaskStateRunning || _state == FIRStorageTaskStateProgress) {
|
||||
[self fireHandlers:_progressHandlers snapshot:snapshot];
|
||||
}
|
||||
break;
|
||||
|
||||
case FIRStorageTaskStatusSuccess:
|
||||
@synchronized(self) {
|
||||
[_successHandlers setValue:callback forKey:UUIDString];
|
||||
} // @synchronized(self)
|
||||
if (_state == FIRStorageTaskStateSuccess) {
|
||||
[self fireHandlers:_successHandlers snapshot:snapshot];
|
||||
}
|
||||
break;
|
||||
|
||||
case FIRStorageTaskStatusFailure:
|
||||
@synchronized(self) {
|
||||
[_failureHandlers setValue:callback forKey:UUIDString];
|
||||
} // @synchronized(self)
|
||||
if (_state == FIRStorageTaskStateFailing || _state == FIRStorageTaskStateFailed) {
|
||||
[self fireHandlers:_failureHandlers snapshot:snapshot];
|
||||
}
|
||||
break;
|
||||
|
||||
case FIRStorageTaskStatusUnknown:
|
||||
// Fall through to exception case if an unknown status is passed
|
||||
|
||||
default:
|
||||
[NSException raise:NSInternalInconsistencyException
|
||||
format:kFIRStorageInvalidObserverStatus, nil];
|
||||
break;
|
||||
}
|
||||
|
||||
@synchronized(self) {
|
||||
_handleToStatusMap[UUIDString] = @(status);
|
||||
} // @synchronized(self)
|
||||
|
||||
return UUIDString;
|
||||
}
|
||||
|
||||
- (void)removeObserverWithHandle:(FIRStorageHandle)handle {
|
||||
FIRStorageTaskStatus status = [_handleToStatusMap[handle] intValue];
|
||||
NSMutableDictionary<NSString *, FIRStorageVoidSnapshot> *observerDictionary =
|
||||
[self handlerDictionaryForStatus:status];
|
||||
|
||||
@synchronized(self) {
|
||||
[observerDictionary removeObjectForKey:handle];
|
||||
[_handleToStatusMap removeObjectForKey:handle];
|
||||
} // @synchronized(self)
|
||||
}
|
||||
|
||||
- (void)removeAllObserversForStatus:(FIRStorageTaskStatus)status {
|
||||
NSMutableDictionary<NSString *, FIRStorageVoidSnapshot> *observerDictionary =
|
||||
[self handlerDictionaryForStatus:status];
|
||||
[self removeHandlersFromStatusMapForDictionary:observerDictionary];
|
||||
|
||||
@synchronized(self) {
|
||||
[observerDictionary removeAllObjects];
|
||||
} // @synchronized(self)
|
||||
}
|
||||
|
||||
- (void)removeAllObservers {
|
||||
@synchronized(self) {
|
||||
[_pauseHandlers removeAllObjects];
|
||||
[_resumeHandlers removeAllObjects];
|
||||
[_progressHandlers removeAllObjects];
|
||||
[_successHandlers removeAllObjects];
|
||||
[_failureHandlers removeAllObjects];
|
||||
[_handleToStatusMap removeAllObjects];
|
||||
} // @synchronized(self)
|
||||
}
|
||||
|
||||
- (NSMutableDictionary<NSString *, FIRStorageVoidSnapshot> *)handlerDictionaryForStatus:
|
||||
(FIRStorageTaskStatus)status {
|
||||
switch (status) {
|
||||
case FIRStorageTaskStatusPause:
|
||||
return _pauseHandlers;
|
||||
|
||||
case FIRStorageTaskStatusResume:
|
||||
return _resumeHandlers;
|
||||
|
||||
case FIRStorageTaskStatusProgress:
|
||||
return _progressHandlers;
|
||||
|
||||
case FIRStorageTaskStatusSuccess:
|
||||
return _successHandlers;
|
||||
|
||||
case FIRStorageTaskStatusFailure:
|
||||
return _failureHandlers;
|
||||
|
||||
case FIRStorageTaskStatusUnknown:
|
||||
return [NSMutableDictionary dictionary];
|
||||
|
||||
default:
|
||||
[NSException raise:NSInternalInconsistencyException
|
||||
format:kFIRStorageInvalidObserverStatus, nil];
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeHandlersFromStatusMapForDictionary:
|
||||
(NSMutableDictionary<NSString *, FIRStorageVoidSnapshot> *)dict {
|
||||
@synchronized(self) {
|
||||
[_handleToStatusMap removeObjectsForKeys:dict.allKeys];
|
||||
} // @synchronized(self)
|
||||
}
|
||||
|
||||
- (void)fireHandlersForStatus:(FIRStorageTaskStatus)status
|
||||
snapshot:(FIRStorageTaskSnapshot *)snapshot {
|
||||
NSMutableDictionary<NSString *, FIRStorageVoidSnapshot> *observerDictionary =
|
||||
[self handlerDictionaryForStatus:status];
|
||||
[self fireHandlers:observerDictionary snapshot:snapshot];
|
||||
}
|
||||
|
||||
- (void)fireHandlers:(NSMutableDictionary<NSString *, FIRStorageVoidSnapshot> *)handlers
|
||||
snapshot:(FIRStorageTaskSnapshot *)snapshot {
|
||||
dispatch_queue_t callbackQueue = self.fetcherService.callbackQueue;
|
||||
if (!callbackQueue) {
|
||||
callbackQueue = dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
// TODO: iterate over this list in a consistent order
|
||||
NSMutableDictionary<NSString *, FIRStorageVoidSnapshot> *handlersCopy;
|
||||
@synchronized(self) {
|
||||
handlersCopy = [handlers copy];
|
||||
} // @synchronized(self)
|
||||
[handlersCopy
|
||||
enumerateKeysAndObjectsUsingBlock:^(
|
||||
NSString *_Nonnull key, FIRStorageVoidSnapshot _Nonnull handler, BOOL *_Nonnull stop) {
|
||||
dispatch_async(callbackQueue, ^{
|
||||
handler(snapshot);
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageObservableTask.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class FIRStorageReference;
|
||||
@class FIRStorageTaskSnapshot;
|
||||
@class GTMSessionFetcherService;
|
||||
|
||||
@interface FIRStorageObservableTask ()
|
||||
|
||||
/**
|
||||
* Creates a new FIRStorageTask initialized with a FIRStorageReference and GTMSessionFetcherService.
|
||||
* @param reference A FIRStorageReference the task will be performed on.
|
||||
* @param service A GTMSessionFetcherService which provides the fetchers and configuration for
|
||||
* requests.
|
||||
* @param queue The shared queue to use for all Storage operations.
|
||||
* @return A new FIRStorageTask representing the current task.
|
||||
*/
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue;
|
||||
|
||||
/**
|
||||
* Raise events for a given task status by passing along a snapshot of existing task state.
|
||||
* @param status A FIRStorageTaskStatus to raise events for.
|
||||
* @param snapshot A FIRStorageTaskSnapshot snapshot of task state to pass through the handler.
|
||||
*/
|
||||
- (void)fireHandlersForStatus:(FIRStorageTaskStatus)status
|
||||
snapshot:(FIRStorageTaskSnapshot *)snapshot;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* Represents a path in GCS, which can be represented as: gs://bucket/path/to/object
|
||||
* or http[s]://firebasestorage.googleapis.com/v0/b/bucket/o/path/to/object?token=<12345>
|
||||
* This class also includes helper methods to parse those URI/Ls, as well as to
|
||||
* add and remove path segments.
|
||||
*/
|
||||
@interface FIRStoragePath : NSObject
|
||||
|
||||
/**
|
||||
* The GCS bucket in the path.
|
||||
*/
|
||||
@property(copy, nonatomic) NSString *bucket;
|
||||
|
||||
/**
|
||||
* The GCS object in the path.
|
||||
*/
|
||||
@property(copy, nonatomic, nullable) NSString *object;
|
||||
|
||||
/**
|
||||
* Parses a generic string (representing some URI or URL) and returns the appropriate path.
|
||||
* @param string String which is parsed into a path.
|
||||
* @return Returns an instance of FIRStoragePath or nil if one can't be created.
|
||||
* @throws Throws an exception if the string is not a valid gs:// URI or http[s]:// URL.
|
||||
*/
|
||||
+ (nullable FIRStoragePath *)pathFromString:(NSString *)string;
|
||||
|
||||
/**
|
||||
* Parses a gs://bucket/path/to/object URI into a GCS path.
|
||||
* @param aURIString gs:// URI which is parsed into a path.
|
||||
* @return Returns an instance of FIRStoragePath or nil if one can't be created.
|
||||
* @throws Throws an exception if the string is not a valid gs:// URI.
|
||||
*/
|
||||
+ (nullable FIRStoragePath *)pathFromGSURI:(NSString *)aURIString;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* Constructs an FIRStoragePath object that represents the given bucket and object.
|
||||
* @param bucket The name of the bucket.
|
||||
* @param object The name of the object.
|
||||
* @return An instance of FIRStoragePath representing the @a bucket and @a object.
|
||||
*/
|
||||
- (instancetype)initWithBucket:(NSString *)bucket
|
||||
object:(nullable NSString *)object NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Parses a http[s]://firebasestorage.googleapis.com/v0/b/bucket/o/path/to/object...?token=<12345>
|
||||
* URL into a GCS path.
|
||||
* @param aURLString http[s]:// URL which is parsed into a path.
|
||||
* string which is parsed into a path.
|
||||
* @return Returns an instance of FIRStoragePath or nil if one can't be created.
|
||||
* @throws Throws an exception if the string is not a valid http[s]:// URL.
|
||||
*/
|
||||
+ (nullable FIRStoragePath *)pathFromHTTPURL:(NSString *)aURLString;
|
||||
|
||||
/**
|
||||
* Creates a new path based off of the current path and a string appended to it.
|
||||
* Note that all slashes are compressed to a single slash, and leading and trailing slashes
|
||||
* are removed.
|
||||
* @param path String to append to the current path.
|
||||
* @return Returns a new instance of FIRStoragePath with the new path appended.
|
||||
*/
|
||||
- (FIRStoragePath *)child:(NSString *)path;
|
||||
|
||||
/**
|
||||
* Creates a new path based off of the current path with the last path segment removed.
|
||||
* @return Returns a new instance of FIRStoragePath pointing to the parent path,
|
||||
* or nil if the current path points to the root.
|
||||
*/
|
||||
- (nullable FIRStoragePath *)parent;
|
||||
|
||||
/**
|
||||
* Creates a new path based off of the root of the bucket.
|
||||
* @return Returns a new instance of FIRStoragePath pointing to the root of the bucket.
|
||||
*/
|
||||
- (FIRStoragePath *)root;
|
||||
|
||||
/**
|
||||
* Returns a GS URI representing the current path.
|
||||
* @return Returns a gs://bucket/path/to/object URI representing the current path.
|
||||
*/
|
||||
- (NSString *)stringValue;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,195 @@
|
||||
// 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 "FirebaseStorage/Sources/FIRStoragePath.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h"
|
||||
|
||||
@implementation FIRStoragePath
|
||||
|
||||
#pragma mark - Class methods
|
||||
|
||||
+ (nullable FIRStoragePath *)pathFromString:(NSString *)string {
|
||||
if ([string hasPrefix:@"gs://"]) {
|
||||
// "gs://bucket/path/to/object"
|
||||
return [FIRStoragePath pathFromGSURI:string];
|
||||
} else if ([string hasPrefix:@"http://"] || [string hasPrefix:@"https://"]) {
|
||||
// "http[s]://firebasestorage.googleapis.com/bucket/path/to/object?signed_url_params"
|
||||
return [FIRStoragePath pathFromHTTPURL:string];
|
||||
} else {
|
||||
// Invalid scheme, raise an exception!
|
||||
[NSException raise:NSInternalInconsistencyException
|
||||
format:@"URL scheme must be one of gs://, http://, or https:// "];
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
+ (nullable FIRStoragePath *)pathFromGSURI:(NSString *)aURIString {
|
||||
NSString *bucketName;
|
||||
NSString *objectName;
|
||||
NSScanner *scanner = [NSScanner scannerWithString:aURIString];
|
||||
BOOL isGSURI = [scanner scanString:@"gs://" intoString:NULL];
|
||||
BOOL hasBucket = [scanner scanUpToString:@"/" intoString:&bucketName];
|
||||
[scanner scanString:@"/" intoString:NULL];
|
||||
[scanner scanUpToString:@"\n" intoString:&objectName];
|
||||
|
||||
if (!isGSURI || !hasBucket) {
|
||||
[NSException raise:NSInternalInconsistencyException
|
||||
format:@"URI must be in the form of gs://<bucket>/<path/to/object>"];
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [[self alloc] initWithBucket:bucketName object:objectName];
|
||||
}
|
||||
|
||||
+ (nullable FIRStoragePath *)pathFromHTTPURL:(NSString *)aURLString {
|
||||
NSString *bucketName;
|
||||
NSString *objectName;
|
||||
NSURL *httpsURL = [NSURL URLWithString:aURLString];
|
||||
NSArray *pathComponents = httpsURL.pathComponents; // [/, v0, b, <bucket>, o, <objects/...>]
|
||||
|
||||
if ([pathComponents count] <= 3 || ![pathComponents[1] isEqual:@"v0"] ||
|
||||
![pathComponents[2] isEqual:@"b"]) {
|
||||
[NSException raise:NSInternalInconsistencyException
|
||||
format:@"URL must be in the form of "
|
||||
@"http[s]://<host>/v0/b/<bucket>/o/<path/to/"
|
||||
@"object>[?token=signed_url_params]"];
|
||||
return nil;
|
||||
}
|
||||
|
||||
bucketName = pathComponents[3];
|
||||
|
||||
// Have an object name
|
||||
if ([pathComponents count] > 5) {
|
||||
NSRange objectRange = NSMakeRange(5, [pathComponents count] - 5);
|
||||
objectName = [[pathComponents subarrayWithRange:objectRange] componentsJoinedByString:@"/"];
|
||||
}
|
||||
|
||||
if (objectName.length == 0) {
|
||||
objectName = nil;
|
||||
}
|
||||
|
||||
return [[self alloc] initWithBucket:bucketName object:objectName];
|
||||
}
|
||||
|
||||
#pragma mark - Initializers
|
||||
|
||||
- (instancetype)initWithBucket:(NSString *)bucket object:(nullable NSString *)object {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_bucket = [bucket copy];
|
||||
_object = [self standardizedPathForString:[object copy]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - NSObject overrides
|
||||
|
||||
- (instancetype)copyWithZone:(NSZone *)zone {
|
||||
return [[[self class] allocWithZone:zone] initWithBucket:_bucket object:_object];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object {
|
||||
if (self == object) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (![object isKindOfClass:[FIRStoragePath class]]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
BOOL isObjectEqual = [self isEqualToFIRStoragePath:(FIRStoragePath *)object];
|
||||
return isObjectEqual;
|
||||
}
|
||||
|
||||
- (BOOL)isEqualToFIRStoragePath:(FIRStoragePath *)path {
|
||||
BOOL isBucketEqual = _bucket == nil && path->_bucket == nil;
|
||||
BOOL isObjectEqual = _object == nil && path->_object == nil;
|
||||
|
||||
if (_bucket && path->_bucket) {
|
||||
isBucketEqual = [_bucket isEqual:path->_bucket];
|
||||
}
|
||||
|
||||
if (_object && path.object) {
|
||||
isObjectEqual = [_object isEqual:path->_object];
|
||||
}
|
||||
|
||||
BOOL isEqual = isBucketEqual && isObjectEqual;
|
||||
return isEqual;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
// "...because in those days, you could XOR anything with anything and get something useful..."
|
||||
// https://www.usenix.org/system/files/1309_14-17_mickens.pdf
|
||||
NSUInteger hash = [_bucket hash] ^ [_object hash];
|
||||
return hash;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"%@ %p: %@", [self class], self, [self stringValue]];
|
||||
}
|
||||
|
||||
- (NSString *)stringValue {
|
||||
return [NSString stringWithFormat:@"gs://%@/%@", _bucket, _object ?: @""];
|
||||
}
|
||||
|
||||
#pragma mark - Public methods
|
||||
|
||||
- (FIRStoragePath *)child:(NSString *)path {
|
||||
if (path.length == 0) {
|
||||
return [self copy]; // Return a copy of the same path, nothing happened
|
||||
}
|
||||
|
||||
NSString *childObject;
|
||||
if (_object == nil) {
|
||||
childObject = path;
|
||||
} else {
|
||||
childObject = [_object stringByAppendingPathComponent:path];
|
||||
}
|
||||
|
||||
FIRStoragePath *childPath = [[FIRStoragePath alloc] initWithBucket:_bucket object:childObject];
|
||||
return childPath;
|
||||
}
|
||||
|
||||
- (nullable FIRStoragePath *)parent {
|
||||
if (_object.length == 0) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString *parentObject = [_object stringByDeletingLastPathComponent];
|
||||
FIRStoragePath *parentPath = [[FIRStoragePath alloc] initWithBucket:_bucket object:parentObject];
|
||||
return parentPath;
|
||||
}
|
||||
|
||||
- (FIRStoragePath *)root {
|
||||
FIRStoragePath *rootPath = [[FIRStoragePath alloc] initWithBucket:_bucket object:nil];
|
||||
return rootPath;
|
||||
}
|
||||
|
||||
#pragma mark - Private methods
|
||||
|
||||
// Removes leading and trailing slashes, and compresses multiple slashes
|
||||
// to create a canonical representation.
|
||||
// Example: /foo//bar///baz//// -> foo/bar/baz
|
||||
- (NSString *)standardizedPathForString:(NSString *)string {
|
||||
NSMutableArray *components = [[string componentsSeparatedByString:@"/"] mutableCopy];
|
||||
NSIndexSet *removedPaths =
|
||||
[components indexesOfObjectsPassingTest:^BOOL(NSString *string, NSUInteger idx, BOOL *stop) {
|
||||
return (string.length == 0);
|
||||
}];
|
||||
[components removeObjectsAtIndexes:removedPaths];
|
||||
return [components componentsJoinedByString:@"/"];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,492 @@
|
||||
// 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageReference.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageDeleteTask.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageDownloadTask_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageGetMetadataTask.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageListResult_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageListTask.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageMetadata_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageReference_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageTask_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageUploadTask_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageUtils.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorage_Private.h"
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageTaskSnapshot.h"
|
||||
|
||||
#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"
|
||||
|
||||
#if SWIFT_PACKAGE
|
||||
@import GTMSessionFetcherCore;
|
||||
#else
|
||||
#import <GTMSessionFetcher/GTMSessionFetcher.h>
|
||||
#import <GTMSessionFetcher/GTMSessionFetcherService.h>
|
||||
#endif
|
||||
|
||||
@implementation FIRStorageReference
|
||||
|
||||
- (instancetype)init {
|
||||
FIRStorage *storage = [FIRStorage storage];
|
||||
NSString *storageBucket = storage.app.options.storageBucket;
|
||||
FIRStoragePath *path = [[FIRStoragePath alloc] initWithBucket:storageBucket object:nil];
|
||||
FIRStorageReference *reference = [self initWithStorage:storage path:path];
|
||||
return reference;
|
||||
}
|
||||
|
||||
- (instancetype)initWithStorage:(FIRStorage *)storage path:(FIRStoragePath *)path {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_storage = storage;
|
||||
_path = path;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - NSObject overrides
|
||||
|
||||
- (instancetype)copyWithZone:(NSZone *)zone {
|
||||
FIRStorageReference *copiedReference = [[[self class] allocWithZone:zone] initWithStorage:_storage
|
||||
path:_path];
|
||||
return copiedReference;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object {
|
||||
if (self == object) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (![object isKindOfClass:[FIRStorageReference class]]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
BOOL isObjectEqual = [self isEqualToFIRStorageReference:(FIRStorageReference *)object];
|
||||
return isObjectEqual;
|
||||
}
|
||||
|
||||
- (BOOL)isEqualToFIRStorageReference:(FIRStorageReference *)reference {
|
||||
BOOL isEqual = [_storage isEqual:reference.storage] && [_path isEqual:reference.path];
|
||||
return isEqual;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
NSUInteger hash = [_storage hash] ^ [_path hash];
|
||||
return hash;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [self stringValue];
|
||||
}
|
||||
|
||||
- (NSString *)stringValue {
|
||||
NSString *value = [NSString stringWithFormat:@"gs://%@/%@", _path.bucket, _path.object ?: @""];
|
||||
return value;
|
||||
}
|
||||
|
||||
#pragma mark - Property Getters
|
||||
|
||||
- (NSString *)bucket {
|
||||
NSString *bucket = _path.bucket;
|
||||
return bucket;
|
||||
}
|
||||
|
||||
- (NSString *)fullPath {
|
||||
NSString *path = _path.object;
|
||||
if (!path) {
|
||||
path = @"";
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
- (NSString *)name {
|
||||
NSString *name = [_path.object lastPathComponent];
|
||||
if (!name) {
|
||||
name = @"";
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
#pragma mark - Path Operations
|
||||
|
||||
- (FIRStorageReference *)root {
|
||||
FIRStoragePath *rootPath = [_path root];
|
||||
FIRStorageReference *rootReference = [[FIRStorageReference alloc] initWithStorage:_storage
|
||||
path:rootPath];
|
||||
return rootReference;
|
||||
}
|
||||
|
||||
- (nullable FIRStorageReference *)parent {
|
||||
FIRStoragePath *parentPath = [_path parent];
|
||||
if (!parentPath) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
FIRStorageReference *parentReference = [[FIRStorageReference alloc] initWithStorage:_storage
|
||||
path:parentPath];
|
||||
return parentReference;
|
||||
}
|
||||
|
||||
- (FIRStorageReference *)child:(NSString *)path {
|
||||
FIRStoragePath *childPath = [_path child:path];
|
||||
FIRStorageReference *childReference = [[FIRStorageReference alloc] initWithStorage:_storage
|
||||
path:childPath];
|
||||
return childReference;
|
||||
}
|
||||
|
||||
#pragma mark - Uploads
|
||||
|
||||
- (FIRStorageUploadTask *)putData:(NSData *)uploadData {
|
||||
return [self putData:uploadData metadata:nil completion:nil];
|
||||
}
|
||||
|
||||
- (FIRStorageUploadTask *)putData:(NSData *)uploadData
|
||||
metadata:(nullable FIRStorageMetadata *)metadata {
|
||||
return [self putData:uploadData metadata:metadata completion:nil];
|
||||
}
|
||||
|
||||
- (FIRStorageUploadTask *)putData:(NSData *)uploadData
|
||||
metadata:(nullable FIRStorageMetadata *)metadata
|
||||
completion:(nullable FIRStorageVoidMetadataError)completion {
|
||||
if (!metadata) {
|
||||
metadata = [[FIRStorageMetadata alloc] init];
|
||||
}
|
||||
|
||||
metadata.path = _path.object;
|
||||
metadata.name = [_path.object lastPathComponent];
|
||||
FIRStorageUploadTask *task =
|
||||
[[FIRStorageUploadTask alloc] initWithReference:self
|
||||
fetcherService:_storage.fetcherServiceForApp
|
||||
dispatchQueue:_storage.dispatchQueue
|
||||
data:uploadData
|
||||
metadata:metadata];
|
||||
|
||||
if (completion) {
|
||||
__block BOOL completed = NO;
|
||||
dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue;
|
||||
if (!callbackQueue) {
|
||||
callbackQueue = dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
[task observeStatus:FIRStorageTaskStatusSuccess
|
||||
handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
|
||||
dispatch_async(callbackQueue, ^{
|
||||
if (!completed) {
|
||||
completed = YES;
|
||||
completion(snapshot.metadata, nil);
|
||||
}
|
||||
});
|
||||
}];
|
||||
[task observeStatus:FIRStorageTaskStatusFailure
|
||||
handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
|
||||
dispatch_async(callbackQueue, ^{
|
||||
if (!completed) {
|
||||
completed = YES;
|
||||
completion(nil, snapshot.error);
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
[task enqueue];
|
||||
return task;
|
||||
}
|
||||
|
||||
- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL {
|
||||
return [self putFile:fileURL metadata:nil completion:nil];
|
||||
}
|
||||
|
||||
- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL
|
||||
metadata:(nullable FIRStorageMetadata *)metadata {
|
||||
return [self putFile:fileURL metadata:metadata completion:nil];
|
||||
}
|
||||
|
||||
- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL
|
||||
metadata:(nullable FIRStorageMetadata *)metadata
|
||||
completion:(nullable FIRStorageVoidMetadataError)completion {
|
||||
if (!metadata) {
|
||||
metadata = [[FIRStorageMetadata alloc] init];
|
||||
}
|
||||
|
||||
metadata.path = _path.object;
|
||||
metadata.name = [_path.object lastPathComponent];
|
||||
FIRStorageUploadTask *task =
|
||||
[[FIRStorageUploadTask alloc] initWithReference:self
|
||||
fetcherService:_storage.fetcherServiceForApp
|
||||
dispatchQueue:_storage.dispatchQueue
|
||||
file:fileURL
|
||||
metadata:metadata];
|
||||
|
||||
if (completion) {
|
||||
__block BOOL completed = NO;
|
||||
dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue;
|
||||
if (!callbackQueue) {
|
||||
callbackQueue = dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
[task observeStatus:FIRStorageTaskStatusSuccess
|
||||
handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
|
||||
dispatch_async(callbackQueue, ^{
|
||||
if (!completed) {
|
||||
completed = YES;
|
||||
completion(snapshot.metadata, nil);
|
||||
}
|
||||
});
|
||||
}];
|
||||
[task observeStatus:FIRStorageTaskStatusFailure
|
||||
handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
|
||||
dispatch_async(callbackQueue, ^{
|
||||
if (!completed) {
|
||||
completed = YES;
|
||||
completion(nil, snapshot.error);
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
[task enqueue];
|
||||
return task;
|
||||
}
|
||||
|
||||
#pragma mark - Downloads
|
||||
|
||||
- (FIRStorageDownloadTask *)dataWithMaxSize:(int64_t)size
|
||||
completion:(FIRStorageVoidDataError)completion {
|
||||
__block BOOL completed = NO;
|
||||
FIRStorageDownloadTask *task =
|
||||
[[FIRStorageDownloadTask alloc] initWithReference:self
|
||||
fetcherService:_storage.fetcherServiceForApp
|
||||
dispatchQueue:_storage.dispatchQueue
|
||||
file:nil];
|
||||
|
||||
dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue;
|
||||
if (!callbackQueue) {
|
||||
callbackQueue = dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
[task observeStatus:FIRStorageTaskStatusSuccess
|
||||
handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
|
||||
FIRStorageDownloadTask *task = snapshot.task;
|
||||
dispatch_async(callbackQueue, ^{
|
||||
if (!completed) {
|
||||
completed = YES;
|
||||
completion(task.downloadData, nil);
|
||||
}
|
||||
});
|
||||
}];
|
||||
|
||||
[task observeStatus:FIRStorageTaskStatusFailure
|
||||
handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
|
||||
dispatch_async(callbackQueue, ^{
|
||||
if (!completed) {
|
||||
completed = YES;
|
||||
completion(nil, snapshot.error);
|
||||
}
|
||||
});
|
||||
}];
|
||||
[task
|
||||
observeStatus:FIRStorageTaskStatusProgress
|
||||
handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
|
||||
FIRStorageDownloadTask *task = snapshot.task;
|
||||
if (task.progress.totalUnitCount > size || task.progress.completedUnitCount > size) {
|
||||
NSDictionary *infoDictionary =
|
||||
@{@"totalSize" : @(task.progress.totalUnitCount),
|
||||
@"maxAllowedSize" : @(size)};
|
||||
NSError *error =
|
||||
[FIRStorageErrors errorWithCode:FIRStorageErrorCodeDownloadSizeExceeded
|
||||
infoDictionary:infoDictionary];
|
||||
[task cancelWithError:error];
|
||||
}
|
||||
}];
|
||||
[task enqueue];
|
||||
return task;
|
||||
}
|
||||
|
||||
- (FIRStorageDownloadTask *)writeToFile:(NSURL *)fileURL {
|
||||
return [self writeToFile:fileURL completion:nil];
|
||||
}
|
||||
|
||||
- (FIRStorageDownloadTask *)writeToFile:(NSURL *)fileURL
|
||||
completion:(FIRStorageVoidURLError)completion {
|
||||
FIRStorageDownloadTask *task =
|
||||
[[FIRStorageDownloadTask alloc] initWithReference:self
|
||||
fetcherService:_storage.fetcherServiceForApp
|
||||
dispatchQueue:_storage.dispatchQueue
|
||||
file:fileURL];
|
||||
if (completion) {
|
||||
__block BOOL completed = NO;
|
||||
dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue;
|
||||
if (!callbackQueue) {
|
||||
callbackQueue = dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
[task observeStatus:FIRStorageTaskStatusSuccess
|
||||
handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
|
||||
dispatch_async(callbackQueue, ^{
|
||||
if (!completed) {
|
||||
completed = YES;
|
||||
completion(fileURL, nil);
|
||||
}
|
||||
});
|
||||
}];
|
||||
[task observeStatus:FIRStorageTaskStatusFailure
|
||||
handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
|
||||
dispatch_async(callbackQueue, ^{
|
||||
if (!completed) {
|
||||
completed = YES;
|
||||
completion(nil, snapshot.error);
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
[task enqueue];
|
||||
return task;
|
||||
}
|
||||
|
||||
- (void)downloadURLWithCompletion:(FIRStorageVoidURLError)completion {
|
||||
FIRStorageGetDownloadURLTask *task =
|
||||
[[FIRStorageGetDownloadURLTask alloc] initWithReference:self
|
||||
fetcherService:_storage.fetcherServiceForApp
|
||||
dispatchQueue:_storage.dispatchQueue
|
||||
completion:completion];
|
||||
[task enqueue];
|
||||
}
|
||||
|
||||
#pragma mark - List
|
||||
|
||||
- (void)listWithMaxResults:(int64_t)maxResults completion:(FIRStorageVoidListError)completion {
|
||||
if (maxResults <= 0 || maxResults > 1000) {
|
||||
completion(nil,
|
||||
[FIRStorageUtils storageErrorWithDescription:
|
||||
@"Argument 'maxResults' must be between 1 and 1000 inclusive."
|
||||
code:FIRStorageErrorCodeInvalidArgument]);
|
||||
} else {
|
||||
FIRStorageListTask *task =
|
||||
[[FIRStorageListTask alloc] initWithReference:self
|
||||
fetcherService:_storage.fetcherServiceForApp
|
||||
dispatchQueue:_storage.dispatchQueue
|
||||
pageSize:@(maxResults)
|
||||
previousPageToken:nil
|
||||
completion:completion];
|
||||
[task enqueue];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)listWithMaxResults:(int64_t)maxResults
|
||||
pageToken:(NSString *)pageToken
|
||||
completion:(FIRStorageVoidListError)completion {
|
||||
if (maxResults <= 0 || maxResults > 1000) {
|
||||
completion(nil,
|
||||
[FIRStorageUtils storageErrorWithDescription:
|
||||
@"Argument 'maxResults' must be between 1 and 1000 inclusive."
|
||||
code:FIRStorageErrorCodeInvalidArgument]);
|
||||
} else {
|
||||
FIRStorageListTask *task =
|
||||
[[FIRStorageListTask alloc] initWithReference:self
|
||||
fetcherService:_storage.fetcherServiceForApp
|
||||
dispatchQueue:_storage.dispatchQueue
|
||||
pageSize:@(maxResults)
|
||||
previousPageToken:pageToken
|
||||
completion:completion];
|
||||
[task enqueue];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)listAllWithCompletion:(FIRStorageVoidListError)completion {
|
||||
NSMutableArray *prefixes = [NSMutableArray new];
|
||||
NSMutableArray *items = [NSMutableArray new];
|
||||
|
||||
__weak FIRStorageReference *weakSelf = self;
|
||||
|
||||
__block FIRStorageVoidListError paginatedCompletion =
|
||||
^(FIRStorageListResult *listResult, NSError *error) {
|
||||
if (error) {
|
||||
completion(nil, error);
|
||||
return;
|
||||
}
|
||||
|
||||
FIRStorageReference *strongSelf = weakSelf;
|
||||
if (!strongSelf) {
|
||||
return;
|
||||
}
|
||||
|
||||
[prefixes addObjectsFromArray:listResult.prefixes];
|
||||
[items addObjectsFromArray:listResult.items];
|
||||
|
||||
if (listResult.pageToken) {
|
||||
FIRStorageListTask *nextPage = [[FIRStorageListTask alloc]
|
||||
initWithReference:self
|
||||
fetcherService:strongSelf->_storage.fetcherServiceForApp
|
||||
dispatchQueue:strongSelf->_storage.dispatchQueue
|
||||
pageSize:nil
|
||||
previousPageToken:listResult.pageToken
|
||||
completion:paginatedCompletion];
|
||||
[nextPage enqueue];
|
||||
} else {
|
||||
FIRStorageListResult *result = [[FIRStorageListResult alloc] initWithPrefixes:prefixes
|
||||
items:items
|
||||
pageToken:nil];
|
||||
// Break the retain cycle we set up indirectly by passing the callback to `nextPage`.
|
||||
paginatedCompletion = nil;
|
||||
completion(result, nil);
|
||||
}
|
||||
};
|
||||
|
||||
FIRStorageListTask *task =
|
||||
[[FIRStorageListTask alloc] initWithReference:self
|
||||
fetcherService:_storage.fetcherServiceForApp
|
||||
dispatchQueue:_storage.dispatchQueue
|
||||
pageSize:nil
|
||||
previousPageToken:nil
|
||||
completion:paginatedCompletion];
|
||||
|
||||
[task enqueue];
|
||||
}
|
||||
|
||||
#pragma mark - Metadata Operations
|
||||
|
||||
- (void)metadataWithCompletion:(FIRStorageVoidMetadataError)completion {
|
||||
FIRStorageGetMetadataTask *task =
|
||||
[[FIRStorageGetMetadataTask alloc] initWithReference:self
|
||||
fetcherService:_storage.fetcherServiceForApp
|
||||
dispatchQueue:_storage.dispatchQueue
|
||||
completion:completion];
|
||||
[task enqueue];
|
||||
}
|
||||
|
||||
- (void)updateMetadata:(FIRStorageMetadata *)metadata
|
||||
completion:(nullable FIRStorageVoidMetadataError)completion {
|
||||
FIRStorageUpdateMetadataTask *task =
|
||||
[[FIRStorageUpdateMetadataTask alloc] initWithReference:self
|
||||
fetcherService:_storage.fetcherServiceForApp
|
||||
dispatchQueue:_storage.dispatchQueue
|
||||
metadata:metadata
|
||||
completion:completion];
|
||||
[task enqueue];
|
||||
}
|
||||
|
||||
#pragma mark - Delete
|
||||
|
||||
- (void)deleteWithCompletion:(nullable FIRStorageVoidError)completion {
|
||||
FIRStorageDeleteTask *task =
|
||||
[[FIRStorageDeleteTask alloc] initWithReference:self
|
||||
fetcherService:_storage.fetcherServiceForApp
|
||||
dispatchQueue:_storage.dispatchQueue
|
||||
completion:completion];
|
||||
[task enqueue];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageReference.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStoragePath.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FIRStorageReference ()
|
||||
|
||||
@property(nonatomic, readwrite) FIRStorage *storage;
|
||||
|
||||
/**
|
||||
* The current path which points to an object in the Google Cloud Storage bucket.
|
||||
*/
|
||||
@property(strong, nonatomic) FIRStoragePath *path;
|
||||
|
||||
- (instancetype)initWithStorage:(FIRStorage *)storage
|
||||
path:(FIRStoragePath *)path NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (NSString *)stringValue;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,73 @@
|
||||
// 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageTask.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorage.h"
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageReference.h"
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageTaskSnapshot.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageReference_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageTask_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorage_Private.h"
|
||||
|
||||
#if SWIFT_PACKAGE
|
||||
@import GTMSessionFetcherCore;
|
||||
#else
|
||||
#import <GTMSessionFetcher/GTMSessionFetcherService.h>
|
||||
#endif
|
||||
|
||||
@implementation FIRStorageTask
|
||||
|
||||
- (instancetype)init {
|
||||
@throw [NSException exceptionWithName:@"Attempt to call unavailable initializer."
|
||||
reason:@"init unavailable, use designated initializer"
|
||||
userInfo:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_reference = reference;
|
||||
_baseRequest = [FIRStorageUtils defaultRequestForReference:reference];
|
||||
_fetcherService = service;
|
||||
_fetcherService.maxRetryInterval = _reference.storage.maxOperationRetryInterval;
|
||||
_dispatchQueue = queue;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (FIRStorageTaskSnapshot *)snapshot {
|
||||
@synchronized(self) {
|
||||
NSProgress *progress = [NSProgress progressWithTotalUnitCount:self.progress.totalUnitCount];
|
||||
progress.completedUnitCount = self.progress.completedUnitCount;
|
||||
FIRStorageTaskSnapshot *snapshot =
|
||||
[[FIRStorageTaskSnapshot alloc] initWithTask:self
|
||||
state:self.state
|
||||
metadata:self.metadata
|
||||
reference:self.reference
|
||||
progress:progress
|
||||
error:[self.error copy]];
|
||||
return snapshot;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dispatchAsync:(void (^)(void))block {
|
||||
dispatch_async(self.dispatchQueue, block);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,88 @@
|
||||
// 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageTaskSnapshot.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageTask_Private.h"
|
||||
|
||||
@implementation FIRStorageTaskSnapshot
|
||||
|
||||
- (instancetype)initWithTask:(__kindof FIRStorageTask *)task
|
||||
state:(FIRStorageTaskState)state
|
||||
metadata:(nullable FIRStorageMetadata *)metadata
|
||||
reference:(FIRStorageReference *)reference
|
||||
progress:(nullable NSProgress *)progress
|
||||
error:(nullable NSError *)error {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_task = task;
|
||||
_metadata = metadata;
|
||||
_reference = reference;
|
||||
_progress = progress;
|
||||
_error = error;
|
||||
|
||||
switch (state) {
|
||||
case FIRStorageTaskStateQueueing:
|
||||
case FIRStorageTaskStateRunning:
|
||||
case FIRStorageTaskStateResuming:
|
||||
_status = FIRStorageTaskStatusResume;
|
||||
break;
|
||||
|
||||
case FIRStorageTaskStateProgress:
|
||||
_status = FIRStorageTaskStatusProgress;
|
||||
break;
|
||||
|
||||
case FIRStorageTaskStatePaused:
|
||||
case FIRStorageTaskStatePausing:
|
||||
_status = FIRStorageTaskStatusPause;
|
||||
break;
|
||||
|
||||
case FIRStorageTaskStateSuccess:
|
||||
case FIRStorageTaskStateCompleting:
|
||||
_status = FIRStorageTaskStatusSuccess;
|
||||
break;
|
||||
|
||||
case FIRStorageTaskStateCancelled:
|
||||
case FIRStorageTaskStateFailing:
|
||||
case FIRStorageTaskStateFailed:
|
||||
_status = FIRStorageTaskStatusFailure;
|
||||
break;
|
||||
|
||||
default:
|
||||
_status = FIRStorageTaskStatusUnknown;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
switch (_status) {
|
||||
case FIRStorageTaskStatusResume:
|
||||
return @"<State: Resume>";
|
||||
case FIRStorageTaskStatusProgress:
|
||||
return [NSString stringWithFormat:@"<State: Progress, Progress: %@>", _progress];
|
||||
case FIRStorageTaskStatusPause:
|
||||
return @"<State: Paused>";
|
||||
case FIRStorageTaskStatusSuccess:
|
||||
return @"<State: Success>";
|
||||
case FIRStorageTaskStatusFailure:
|
||||
return [NSString stringWithFormat:@"<State: Failed, Error: %@>", _error];
|
||||
default:
|
||||
return @"<State: Unknown>";
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageTaskSnapshot.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class FIRStorageMetadata;
|
||||
@class FIRStorageReference;
|
||||
@class FIRStorageTask;
|
||||
|
||||
@interface FIRStorageTaskSnapshot ()
|
||||
|
||||
@property(readwrite, copy, nonatomic) FIRStorageTask *task;
|
||||
@property(readwrite, copy, nonatomic) FIRStorageMetadata *metadata;
|
||||
@property(readwrite, copy, nonatomic) FIRStorageReference *reference;
|
||||
@property(readwrite, strong, nonatomic) NSProgress *progress;
|
||||
@property(readwrite, copy, nonatomic) NSError *error;
|
||||
|
||||
/**
|
||||
* Creates a new task snapshot from the given properties.
|
||||
* @param task The task being represented in this snapshot.
|
||||
* @param state The current state of the parent task.
|
||||
* @param metadata The FIRStorageMetadata of a task. Before upload/update, contains the metadata
|
||||
* to be updated; after, contains the returned metadata. May be nil if no metadata is provided
|
||||
* or returned.
|
||||
* @param reference The FIRStorageReference that spawned the task this snapshot is based on.
|
||||
* @param progress An NSProgress object containing progress of the task this snapshot is based on,
|
||||
* or nil if the task doesn't report progress.
|
||||
* @param error An NSError object containing an error that occurred during the task,
|
||||
* if one occurred.
|
||||
* @return Returns the constructed snapshot.
|
||||
*/
|
||||
- (instancetype)initWithTask:(__kindof FIRStorageTask *)task
|
||||
state:(FIRStorageTaskState)state
|
||||
metadata:(nullable FIRStorageMetadata *)metadata
|
||||
reference:(FIRStorageReference *)reference
|
||||
progress:(nullable NSProgress *)progress
|
||||
error:(nullable NSError *)error;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageReference.h"
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageTaskSnapshot.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageErrors.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageReference_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageUtils.h"
|
||||
|
||||
#if SWIFT_PACKAGE
|
||||
@import GTMSessionFetcherCore;
|
||||
#else
|
||||
#import <GTMSessionFetcher/GTMSessionFetcher.h>
|
||||
#import <GTMSessionFetcher/GTMSessionFetcherService.h>
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FIRStorageTask ()
|
||||
|
||||
/**
|
||||
* State for the current task in progress.
|
||||
*/
|
||||
@property(atomic) FIRStorageTaskState state;
|
||||
|
||||
/**
|
||||
* FIRStorageMetadata for the task in progress, or nil if none present.
|
||||
*/
|
||||
@property(strong, nonatomic, nullable) FIRStorageMetadata *metadata;
|
||||
|
||||
/**
|
||||
* Error which occurred during task execution, or nil if no error occurred.
|
||||
*/
|
||||
@property(strong, nonatomic, nullable) NSError *error;
|
||||
|
||||
/**
|
||||
* NSProgress object which tracks the progress of an observable task.
|
||||
*/
|
||||
@property(strong, nonatomic) NSProgress *progress;
|
||||
|
||||
/**
|
||||
* Reference pointing to the location the task is being performed against.
|
||||
*/
|
||||
@property(strong, nonatomic) FIRStorageReference *reference;
|
||||
|
||||
/**
|
||||
* A serial queue for all storage operations.
|
||||
*/
|
||||
@property(nonatomic, readonly) dispatch_queue_t dispatchQueue;
|
||||
|
||||
@property(strong, readwrite, nonatomic, nonnull) FIRStorageTaskSnapshot *snapshot;
|
||||
|
||||
@property(readonly, copy, nonatomic) NSURLRequest *baseRequest;
|
||||
|
||||
@property(strong, atomic) GTMSessionFetcher *fetcher;
|
||||
|
||||
@property(readonly, nonatomic) GTMSessionFetcherService *fetcherService;
|
||||
|
||||
@property(readonly, copy) GTMSessionFetcherCompletionHandler fetcherCompletion;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* Creates a new FIRStorageTask initialized with a FIRStorageReference and GTMSessionFetcherService.
|
||||
* @param reference A FIRStorageReference the task will be performed on.
|
||||
* @param service A GTMSessionFetcherService which provides the fetchers and configuration for
|
||||
* requests.
|
||||
* @param queue The shared queue to use for all Storage operations.
|
||||
* @return A new FIRStorageTask representing the current task.
|
||||
*/
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/** Dispatches a block on the shared Storage queue. */
|
||||
- (void)dispatchAsync:(void (^)(void))block;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if SWIFT_PACKAGE
|
||||
@import GTMSessionFetcherCore;
|
||||
#else
|
||||
#import <GTMSessionFetcher/GTMSessionFetcherService.h>
|
||||
#endif
|
||||
|
||||
@protocol FIRAuthInterop;
|
||||
@protocol FIRAppCheckInterop;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* Wrapper class for FIRAuthInterop that implements the GTMFetcherAuthorizationProtocol,
|
||||
* so as to easily provide GTMSessionFetcher fetches a Firebase Authentication JWT
|
||||
* for the current logged in user. Handles token expiration and other failure cases.
|
||||
* If no authentication provider exists or no token is found, no token is added
|
||||
* and the request is passed.
|
||||
*/
|
||||
@interface FIRStorageTokenAuthorizer : NSObject <GTMFetcherAuthorizationProtocol>
|
||||
|
||||
/**
|
||||
* Initializes the token authorizer with an instance of FIRApp.
|
||||
* @param googleAppID The Google AppID of the app to send with the request.
|
||||
* @param auth An instance that provides access to Auth functionality, if it exists.
|
||||
* @param appCheck An instance that provides access to AppCheck functionality, if it exists.
|
||||
* @return Returns an instance of FIRStorageTokenAuthorizer which adds the appropriate
|
||||
* "Authorization" header to all outbound requests. Note that a token may not be added
|
||||
* if the Auth instance is nil. This allows for unauthenticated access, if Firebase
|
||||
* Storage rules allow for it.
|
||||
*/
|
||||
- (instancetype)initWithGoogleAppID:(NSString *)googleAppID
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
authProvider:(nullable id<FIRAuthInterop>)auth
|
||||
appCheck:(nullable id<FIRAppCheckInterop>)appCheck;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,166 @@
|
||||
// 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 "FirebaseStorage/Sources/FIRStorageTokenAuthorizer.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorage.h"
|
||||
#import "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageConstants.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageErrors.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageLogger.h"
|
||||
|
||||
#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"
|
||||
|
||||
#import "FirebaseAppCheck/Sources/Interop/FIRAppCheckInterop.h"
|
||||
#import "FirebaseAppCheck/Sources/Interop/FIRAppCheckTokenResultInterop.h"
|
||||
#import "Interop/Auth/Public/FIRAuthInterop.h"
|
||||
|
||||
static NSString *const kAppCheckTokenHeader = @"X-Firebase-AppCheck";
|
||||
static NSString *const kAuthHeader = @"Authorization";
|
||||
|
||||
@implementation FIRStorageTokenAuthorizer {
|
||||
@private
|
||||
/// Google App ID to pass along with each request.
|
||||
NSString *_googleAppID;
|
||||
|
||||
/// Auth provider.
|
||||
id<FIRAuthInterop> _auth;
|
||||
id<FIRAppCheckInterop> _appCheck;
|
||||
}
|
||||
|
||||
@synthesize fetcherService = _fetcherService;
|
||||
|
||||
- (instancetype)initWithGoogleAppID:(NSString *)googleAppID
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
authProvider:(nullable id<FIRAuthInterop>)auth
|
||||
appCheck:(nullable id<FIRAppCheckInterop>)appCheck {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_googleAppID = googleAppID;
|
||||
_fetcherService = service;
|
||||
_auth = auth;
|
||||
_appCheck = appCheck;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - GTMFetcherAuthorizationProtocol methods
|
||||
|
||||
- (void)authorizeRequest:(NSMutableURLRequest *)request
|
||||
delegate:(id)delegate
|
||||
didFinishSelector:(SEL)sel {
|
||||
// Set version header on each request
|
||||
NSString *versionString = [NSString stringWithFormat:@"ios/%@", FIRFirebaseVersion()];
|
||||
[request setValue:versionString forHTTPHeaderField:@"x-firebase-storage-version"];
|
||||
|
||||
// Set GMP ID on each request
|
||||
[request setValue:_googleAppID forHTTPHeaderField:@"x-firebase-gmpid"];
|
||||
|
||||
if (delegate && sel) {
|
||||
id selfParam = self;
|
||||
NSMethodSignature *sig = [delegate methodSignatureForSelector:sel];
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
|
||||
[invocation setSelector:sel];
|
||||
[invocation setTarget:delegate];
|
||||
[invocation setArgument:&selfParam atIndex:2];
|
||||
[invocation setArgument:&request atIndex:3];
|
||||
|
||||
dispatch_queue_t callbackQueue = self.fetcherService.callbackQueue;
|
||||
if (!callbackQueue) {
|
||||
callbackQueue = dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
[invocation retainArguments];
|
||||
|
||||
dispatch_group_t fetchTokenGroup = dispatch_group_create();
|
||||
|
||||
if (_auth) {
|
||||
dispatch_group_enter(fetchTokenGroup);
|
||||
|
||||
[_auth getTokenForcingRefresh:NO
|
||||
withCallback:^(NSString *_Nullable token, NSError *_Nullable error) {
|
||||
if (error) {
|
||||
NSMutableDictionary *errorDictionary =
|
||||
[NSMutableDictionary dictionaryWithDictionary:error.userInfo];
|
||||
errorDictionary[kFIRStorageResponseErrorDomain] = error.domain;
|
||||
errorDictionary[kFIRStorageResponseErrorCode] = @(error.code);
|
||||
|
||||
NSError *tokenError =
|
||||
[FIRStorageErrors errorWithCode:FIRStorageErrorCodeUnauthenticated
|
||||
infoDictionary:errorDictionary];
|
||||
[invocation setArgument:&tokenError atIndex:4];
|
||||
} else if (token) {
|
||||
NSString *firebaseToken =
|
||||
[NSString stringWithFormat:kFIRStorageAuthTokenFormat, token];
|
||||
[request setValue:firebaseToken forHTTPHeaderField:kAuthHeader];
|
||||
}
|
||||
|
||||
dispatch_group_leave(fetchTokenGroup);
|
||||
}];
|
||||
}
|
||||
|
||||
if (_appCheck) {
|
||||
dispatch_group_enter(fetchTokenGroup);
|
||||
|
||||
[_appCheck getTokenForcingRefresh:NO
|
||||
completion:^(id<FIRAppCheckTokenResultInterop> tokenResult) {
|
||||
[request setValue:tokenResult.token
|
||||
forHTTPHeaderField:kAppCheckTokenHeader];
|
||||
|
||||
if (tokenResult.error) {
|
||||
FIRLogDebug(kFIRLoggerStorage, kFIRStorageMessageCodeAppCheckError,
|
||||
@"Failed to fetch AppCheck token. Error: %@",
|
||||
tokenResult.error);
|
||||
}
|
||||
|
||||
dispatch_group_leave(fetchTokenGroup);
|
||||
}];
|
||||
}
|
||||
|
||||
dispatch_group_notify(fetchTokenGroup, callbackQueue, ^{
|
||||
[invocation invoke];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Note that stopAuthorization, isAuthorizingRequest, and userEmail
|
||||
// aren't relevant with the Firebase App/Auth implementation of tokens,
|
||||
// and thus aren't implemented. Token refresh is handled transparently
|
||||
// for us, and we don't allow the auth request to be stopped.
|
||||
// Auth is also not required so the world doesn't stop.
|
||||
- (void)stopAuthorization {
|
||||
// Noop
|
||||
}
|
||||
|
||||
- (void)stopAuthorizationForRequest:(NSURLRequest *)request {
|
||||
// Noop
|
||||
}
|
||||
|
||||
- (BOOL)isAuthorizingRequest:(NSURLRequest *)request {
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)isAuthorizedRequest:(NSURLRequest *)request {
|
||||
NSString *authHeader = request.allHTTPHeaderFields[@"Authorization"];
|
||||
BOOL isFirebaseToken = [authHeader hasPrefix:@"Firebase"];
|
||||
return isFirebaseToken;
|
||||
}
|
||||
|
||||
- (NSString *)userEmail {
|
||||
// Noop
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageTask.h"
|
||||
|
||||
@class GTMSessionFetcherService;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* Task which provides the ability update the metadata on an object in Firebase Storage.
|
||||
*/
|
||||
@interface FIRStorageUpdateMetadataTask : FIRStorageTask <FIRStorageTaskManagement>
|
||||
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue
|
||||
metadata:(FIRStorageMetadata *)metadata
|
||||
completion:(FIRStorageVoidMetadataError)completion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
// 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 "FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageMetadata_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageTask_Private.h"
|
||||
|
||||
@implementation FIRStorageUpdateMetadataTask {
|
||||
@private
|
||||
FIRStorageVoidMetadataError _completion;
|
||||
// Metadata used in the update request
|
||||
FIRStorageMetadata *_updateMetadata;
|
||||
}
|
||||
|
||||
@synthesize fetcher = _fetcher;
|
||||
@synthesize fetcherCompletion = _fetcherCompletion;
|
||||
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue
|
||||
metadata:(FIRStorageMetadata *)metadata
|
||||
completion:(FIRStorageVoidMetadataError)completion {
|
||||
self = [super initWithReference:reference fetcherService:service dispatchQueue:queue];
|
||||
if (self) {
|
||||
_updateMetadata = [metadata copy];
|
||||
_completion = [completion copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_fetcher stopFetching];
|
||||
}
|
||||
|
||||
- (void)enqueue {
|
||||
__weak FIRStorageUpdateMetadataTask *weakSelf = self;
|
||||
|
||||
[self dispatchAsync:^() {
|
||||
FIRStorageUpdateMetadataTask *strongSelf = weakSelf;
|
||||
|
||||
if (!strongSelf) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy];
|
||||
NSDictionary *updateDictionary = [strongSelf->_updateMetadata updatedMetadata];
|
||||
NSData *updateData = [NSData frs_dataFromJSONDictionary:updateDictionary];
|
||||
request.HTTPMethod = @"PATCH";
|
||||
request.timeoutInterval = strongSelf.reference.storage.maxOperationRetryTime;
|
||||
request.HTTPBody = updateData;
|
||||
NSString *typeString = @"application/json; charset=UTF-8";
|
||||
[request setValue:typeString forHTTPHeaderField:@"Content-Type"];
|
||||
NSString *lengthString = [NSString stringWithFormat:@"%zu", (unsigned long)[updateData length]];
|
||||
[request setValue:lengthString forHTTPHeaderField:@"Content-Length"];
|
||||
|
||||
FIRStorageVoidMetadataError callback = strongSelf->_completion;
|
||||
strongSelf->_completion = nil;
|
||||
|
||||
GTMSessionFetcher *fetcher = [strongSelf.fetcherService fetcherWithRequest:request];
|
||||
strongSelf->_fetcher = fetcher;
|
||||
|
||||
strongSelf->_fetcherCompletion = ^(NSData *data, NSError *error) {
|
||||
FIRStorageMetadata *metadata;
|
||||
if (error) {
|
||||
if (!self.error) {
|
||||
self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference];
|
||||
}
|
||||
} else {
|
||||
NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data];
|
||||
if (responseDictionary) {
|
||||
metadata = [[FIRStorageMetadata alloc] initWithDictionary:responseDictionary];
|
||||
[metadata setType:FIRStorageMetadataTypeFile];
|
||||
} else {
|
||||
self.error = [FIRStorageErrors errorWithInvalidRequest:data];
|
||||
}
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback(metadata, self.error);
|
||||
}
|
||||
self->_fetcherCompletion = nil;
|
||||
};
|
||||
|
||||
fetcher.comment = @"UpdateMetadataTask";
|
||||
|
||||
[fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) {
|
||||
FIRStorageUpdateMetadataTask *strongSelf = weakSelf;
|
||||
if (strongSelf.fetcherCompletion) {
|
||||
strongSelf.fetcherCompletion(data, error);
|
||||
}
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,277 @@
|
||||
// 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 "FirebaseStorage/Sources/Public/FirebaseStorage/FIRStorageUploadTask.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageMetadata_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageObservableTask_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageTask_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageUploadTask_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorage_Private.h"
|
||||
|
||||
#if SWIFT_PACKAGE
|
||||
@import GTMSessionFetcherCore;
|
||||
#else
|
||||
#import <GTMSessionFetcher/GTMSessionUploadFetcher.h>
|
||||
#endif
|
||||
|
||||
@implementation FIRStorageUploadTask
|
||||
|
||||
@synthesize progress = _progress;
|
||||
@synthesize fetcherCompletion = _fetcherCompletion;
|
||||
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue
|
||||
data:(NSData *)uploadData
|
||||
metadata:(FIRStorageMetadata *)metadata {
|
||||
self = [super initWithReference:reference fetcherService:service dispatchQueue:queue];
|
||||
if (self) {
|
||||
_uploadMetadata = [metadata copy];
|
||||
_uploadData = [uploadData copy];
|
||||
_progress = [NSProgress progressWithTotalUnitCount:[_uploadData length]];
|
||||
|
||||
if (!_uploadMetadata.contentType) {
|
||||
_uploadMetadata.contentType = @"application/octet-stream";
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue
|
||||
file:(NSURL *)fileURL
|
||||
metadata:(FIRStorageMetadata *)metadata {
|
||||
self = [super initWithReference:reference fetcherService:service dispatchQueue:queue];
|
||||
if (self) {
|
||||
_uploadMetadata = [metadata copy];
|
||||
_fileURL = [fileURL copy];
|
||||
_progress = [NSProgress progressWithTotalUnitCount:0];
|
||||
|
||||
NSString *mimeType = [FIRStorageUtils MIMETypeForExtension:[_fileURL pathExtension]];
|
||||
|
||||
if (!_uploadMetadata.contentType) {
|
||||
_uploadMetadata.contentType = mimeType ?: @"application/octet-stream";
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_uploadFetcher stopFetching];
|
||||
}
|
||||
|
||||
- (void)enqueue {
|
||||
__weak FIRStorageUploadTask *weakSelf = self;
|
||||
|
||||
[self dispatchAsync:^() {
|
||||
FIRStorageUploadTask *strongSelf = weakSelf;
|
||||
|
||||
if (!strongSelf) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSError *contentValidationError;
|
||||
if (![strongSelf isContentToUploadValid:&contentValidationError]) {
|
||||
strongSelf.error = contentValidationError;
|
||||
[strongSelf finishTaskWithStatus:FIRStorageTaskStatusFailure snapshot:strongSelf.snapshot];
|
||||
return;
|
||||
}
|
||||
|
||||
strongSelf.state = FIRStorageTaskStateQueueing;
|
||||
|
||||
NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy];
|
||||
request.HTTPMethod = @"POST";
|
||||
request.timeoutInterval = strongSelf.reference.storage.maxUploadRetryTime;
|
||||
NSData *bodyData =
|
||||
[NSData frs_dataFromJSONDictionary:[strongSelf->_uploadMetadata dictionaryRepresentation]];
|
||||
request.HTTPBody = bodyData;
|
||||
[request setValue:@"application/json; charset=UTF-8" forHTTPHeaderField:@"Content-Type"];
|
||||
NSString *contentLengthString =
|
||||
[NSString stringWithFormat:@"%zu", (unsigned long)[bodyData length]];
|
||||
[request setValue:contentLengthString forHTTPHeaderField:@"Content-Length"];
|
||||
|
||||
NSURLComponents *components = [NSURLComponents componentsWithURL:request.URL
|
||||
resolvingAgainstBaseURL:NO];
|
||||
|
||||
if ([components.host isEqual:kGCSHost]) {
|
||||
[components setPercentEncodedPath:[@"/upload" stringByAppendingString:components.path]];
|
||||
}
|
||||
|
||||
NSDictionary *queryParams = @{@"uploadType" : @"resumable", @"name" : self.uploadMetadata.path};
|
||||
[components setPercentEncodedQuery:[FIRStorageUtils queryStringForDictionary:queryParams]];
|
||||
request.URL = components.URL;
|
||||
|
||||
GTMSessionUploadFetcher *uploadFetcher =
|
||||
[GTMSessionUploadFetcher uploadFetcherWithRequest:request
|
||||
uploadMIMEType:strongSelf->_uploadMetadata.contentType
|
||||
chunkSize:kGTMSessionUploadFetcherStandardChunkSize
|
||||
fetcherService:self.fetcherService];
|
||||
|
||||
if (strongSelf->_uploadData) {
|
||||
[uploadFetcher setUploadData:strongSelf->_uploadData];
|
||||
uploadFetcher.comment = @"Data UploadTask";
|
||||
} else if (strongSelf->_fileURL) {
|
||||
[uploadFetcher setUploadFileURL:strongSelf->_fileURL];
|
||||
uploadFetcher.comment = @"File UploadTask";
|
||||
}
|
||||
|
||||
uploadFetcher.maxRetryInterval = self.reference.storage.maxUploadRetryInterval;
|
||||
|
||||
[uploadFetcher setSendProgressBlock:^(int64_t bytesSent, int64_t totalBytesSent,
|
||||
int64_t totalBytesExpectedToSend) {
|
||||
weakSelf.state = FIRStorageTaskStateProgress;
|
||||
weakSelf.progress.completedUnitCount = totalBytesSent;
|
||||
weakSelf.progress.totalUnitCount = totalBytesExpectedToSend;
|
||||
weakSelf.metadata = self->_uploadMetadata;
|
||||
[weakSelf fireHandlersForStatus:FIRStorageTaskStatusProgress snapshot:weakSelf.snapshot];
|
||||
weakSelf.state = FIRStorageTaskStateRunning;
|
||||
}];
|
||||
|
||||
strongSelf->_uploadFetcher = uploadFetcher;
|
||||
|
||||
// Process fetches
|
||||
strongSelf.state = FIRStorageTaskStateRunning;
|
||||
|
||||
strongSelf->_fetcherCompletion = ^(NSData *_Nullable data, NSError *_Nullable error) {
|
||||
// Fire last progress updates
|
||||
[self fireHandlersForStatus:FIRStorageTaskStatusProgress snapshot:self.snapshot];
|
||||
|
||||
// Handle potential issues with upload
|
||||
if (error) {
|
||||
self.state = FIRStorageTaskStateFailed;
|
||||
self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference];
|
||||
self.metadata = self->_uploadMetadata;
|
||||
|
||||
[self finishTaskWithStatus:FIRStorageTaskStatusFailure snapshot:self.snapshot];
|
||||
return;
|
||||
}
|
||||
|
||||
// Upload completed successfully, fire completion callbacks
|
||||
self.state = FIRStorageTaskStateSuccess;
|
||||
|
||||
NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data];
|
||||
if (responseDictionary) {
|
||||
FIRStorageMetadata *metadata =
|
||||
[[FIRStorageMetadata alloc] initWithDictionary:responseDictionary];
|
||||
[metadata setType:FIRStorageMetadataTypeFile];
|
||||
self.metadata = metadata;
|
||||
} else {
|
||||
self.error = [FIRStorageErrors errorWithInvalidRequest:data];
|
||||
}
|
||||
|
||||
[self finishTaskWithStatus:FIRStorageTaskStatusSuccess snapshot:self.snapshot];
|
||||
};
|
||||
|
||||
[strongSelf->_uploadFetcher
|
||||
beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) {
|
||||
FIRStorageUploadTask *strongSelf = weakSelf;
|
||||
if (strongSelf.fetcherCompletion) {
|
||||
strongSelf.fetcherCompletion(data, error);
|
||||
}
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)finishTaskWithStatus:(FIRStorageTaskStatus)status
|
||||
snapshot:(FIRStorageTaskSnapshot *)snapshot {
|
||||
[self fireHandlersForStatus:status snapshot:self.snapshot];
|
||||
[self removeAllObservers];
|
||||
self->_fetcherCompletion = nil;
|
||||
}
|
||||
|
||||
- (BOOL)isContentToUploadValid:(NSError **)outError {
|
||||
if (_uploadData != nil) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
NSError *fileReachabilityError;
|
||||
if (![_fileURL checkResourceIsReachableAndReturnError:&fileReachabilityError] ||
|
||||
![self fileURLisFile:_fileURL]) {
|
||||
if (outError != NULL) {
|
||||
NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithCapacity:2];
|
||||
userInfo[NSLocalizedDescriptionKey] = [NSString
|
||||
stringWithFormat:@"File at URL: %@ is not reachable. "
|
||||
@"Ensure file URL is not a directory, symbolic link, or invalid url.",
|
||||
_fileURL.absoluteString];
|
||||
|
||||
if (fileReachabilityError) {
|
||||
userInfo[NSUnderlyingErrorKey] = fileReachabilityError;
|
||||
}
|
||||
|
||||
*outError = [NSError errorWithDomain:FIRStorageErrorDomain
|
||||
code:FIRStorageErrorCodeUnknown
|
||||
userInfo:userInfo];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Upload Management
|
||||
|
||||
- (void)cancel {
|
||||
__weak FIRStorageUploadTask *weakSelf = self;
|
||||
|
||||
[self dispatchAsync:^() {
|
||||
weakSelf.state = FIRStorageTaskStateCancelled;
|
||||
[weakSelf.uploadFetcher stopFetching];
|
||||
if (weakSelf.state != FIRStorageTaskStateSuccess) {
|
||||
weakSelf.metadata = weakSelf.uploadMetadata;
|
||||
}
|
||||
weakSelf.error = [FIRStorageErrors errorWithCode:FIRStorageErrorCodeCancelled];
|
||||
[weakSelf fireHandlersForStatus:FIRStorageTaskStatusFailure snapshot:weakSelf.snapshot];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)pause {
|
||||
__weak FIRStorageUploadTask *weakSelf = self;
|
||||
|
||||
[self dispatchAsync:^() {
|
||||
weakSelf.state = FIRStorageTaskStatePaused;
|
||||
[weakSelf.uploadFetcher pauseFetching];
|
||||
if (weakSelf.state != FIRStorageTaskStateSuccess) {
|
||||
weakSelf.metadata = weakSelf.uploadMetadata;
|
||||
}
|
||||
[weakSelf fireHandlersForStatus:FIRStorageTaskStatusPause snapshot:weakSelf.snapshot];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)resume {
|
||||
__weak FIRStorageUploadTask *weakSelf = self;
|
||||
|
||||
[self dispatchAsync:^() {
|
||||
weakSelf.state = FIRStorageTaskStateResuming;
|
||||
[weakSelf.uploadFetcher resumeFetching];
|
||||
if (weakSelf.state != FIRStorageTaskStateSuccess) {
|
||||
weakSelf.metadata = weakSelf.uploadMetadata;
|
||||
}
|
||||
[weakSelf fireHandlersForStatus:FIRStorageTaskStatusResume snapshot:weakSelf.snapshot];
|
||||
weakSelf.state = FIRStorageTaskStateRunning;
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Private Helpers
|
||||
|
||||
- (BOOL)fileURLisFile:(NSURL *)fileURL {
|
||||
NSNumber *isFile = [NSNumber numberWithBool:NO];
|
||||
[fileURL getResourceValue:&isFile forKey:NSURLIsRegularFileKey error:nil];
|
||||
return [isFile boolValue];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@class GTMSessionUploadFetcher;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FIRStorageUploadTask ()
|
||||
|
||||
/**
|
||||
* The data to be uploaded (if uploading bytes).
|
||||
*/
|
||||
@property(readonly, copy, nonatomic, nullable) NSData *uploadData;
|
||||
|
||||
/**
|
||||
* The name of a file on disk to be uploaded (if uploading from a file).
|
||||
*/
|
||||
@property(readonly, copy, nonatomic, nullable) NSURL *fileURL;
|
||||
|
||||
/**
|
||||
* The FIRStorageMetadata about the object being uploaded.
|
||||
*/
|
||||
@property(readonly, copy, nonatomic) FIRStorageMetadata *uploadMetadata;
|
||||
|
||||
/**
|
||||
* GTMSessionUploadFetcher used by all uploads.
|
||||
*/
|
||||
@property(strong, atomic) GTMSessionUploadFetcher *uploadFetcher;
|
||||
|
||||
/**
|
||||
* Initializes an upload task with a base FIRStorageReference and GTMSessionFetcherService.
|
||||
* @param reference The base FIRStorageReference which fetchers use for configuration.
|
||||
* @param service The GTMSessionFetcherService which will create fetchers.
|
||||
* @param queue The shared queue to use for all Storage operations.
|
||||
* @param uploadData The NSData object to be uploaded.
|
||||
* @return Returns an instance of FIRStorageUploadTask.
|
||||
*/
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue
|
||||
data:(NSData *)uploadData
|
||||
metadata:(FIRStorageMetadata *)metadata;
|
||||
|
||||
/**
|
||||
* Initializes an upload task with a base FIRStorageReference and GTMSessionFetcherService.
|
||||
* @param reference The base FIRStorageReference which fetchers use for configuration.
|
||||
* @param service The GTMSessionFetcherService which will create fetchers.
|
||||
* @param queue The shared queue to use for all Storage operations.
|
||||
* @param fileURL The system file URL to upload from.
|
||||
* @return Returns an instance of FIRStorageUploadTask.
|
||||
*/
|
||||
- (instancetype)initWithReference:(FIRStorageReference *)reference
|
||||
fetcherService:(GTMSessionFetcherService *)service
|
||||
dispatchQueue:(dispatch_queue_t)queue
|
||||
file:(NSURL *)fileURL
|
||||
metadata:(FIRStorageMetadata *)metadata;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
@class FIRStoragePath;
|
||||
@class FIRStorageReference;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* FIRStorageUtils provides a number of helper methods for commonly used operations
|
||||
* in Firebase Storage, such as JSON parsing, escaping, and file extensions.
|
||||
*/
|
||||
@interface FIRStorageUtils : NSObject
|
||||
|
||||
/**
|
||||
* Returns a percent encoded string appropriate for GCS.
|
||||
* See https://cloud.google.com/storage/docs/naming for more details.
|
||||
* @param string A path to escape characters according to the GCS
|
||||
* @return A percent encoded string appropriate for GCS operations or nil if string is nil
|
||||
* or can't be escaped.
|
||||
*/
|
||||
+ (nullable NSString *)GCSEscapedString:(NSString *)string;
|
||||
|
||||
/**
|
||||
* Returns the MIME type for a file extension.
|
||||
* Example of how to get MIME type here: http://ddeville.me/2011/12/mime-to-UTI-cocoa/
|
||||
* @param extension A file extension such as "txt", "png", etc.
|
||||
* @return The MIME type for the input extension such as "text/plain", "image/png", etc.
|
||||
* or nil if no type is found.
|
||||
*/
|
||||
+ (nullable NSString *)MIMETypeForExtension:(NSString *)extension;
|
||||
|
||||
/**
|
||||
* Returns a properly escaped query string from a given dictionary of query items to values.
|
||||
* @param dictionary A dictionary containing query items and associated values.
|
||||
* @return A properly escaped query string or the empty string for a nil or empty dictionary.
|
||||
*/
|
||||
+ (NSString *)queryStringForDictionary:(nullable NSDictionary *)dictionary;
|
||||
|
||||
/**
|
||||
* Returns a base NSURLRequest used by all tasks.
|
||||
* @param reference The FIRStorageReference to create a request for.
|
||||
* @return Returns a properly formatted NSURLRequest of the form:
|
||||
* scheme://host/version/b/<bucket>/o[/path/to/object]
|
||||
*/
|
||||
+ (NSURLRequest *)defaultRequestForReference:(FIRStorageReference *)reference;
|
||||
|
||||
/**
|
||||
* Returns a base NSURLRequest with custom query parameters.
|
||||
* @param reference The FIRStorageReference to create a request for.
|
||||
* @param queryParams A key/value dictionary with query parameters.
|
||||
* @return Returns a formatted NSURLRequest
|
||||
*/
|
||||
+ (NSURLRequest *)defaultRequestForReference:(FIRStorageReference *)reference
|
||||
queryParams:(NSDictionary<NSString *, NSString *> *)queryParams;
|
||||
|
||||
/**
|
||||
* Creates the appropriate GCS percent escaped path for a given FIRStoragePath.
|
||||
* @param path The FIRStoragePath to encode.
|
||||
* @return Returns the GCS encoded URL for a given FIRStoragePath.
|
||||
*/
|
||||
+ (NSString *)encodedURLForPath:(FIRStoragePath *)path;
|
||||
|
||||
/**
|
||||
* Creates a NSError in the Firebase Storage domain with given code and description.
|
||||
* Useful for argument validation.
|
||||
* @param description The error description to surface to the user.
|
||||
* @param code The error code.
|
||||
* @return An NSError in the Firebase Storage error domain.
|
||||
*/
|
||||
+ (NSError *)storageErrorWithDescription:(NSString *)description code:(NSInteger)code;
|
||||
|
||||
/**
|
||||
* Performs a crude translation of the user provided timeouts to the retry intervals that
|
||||
* GTMSessionFetcher accepts. GTMSessionFetcher times out operations if the time between individual
|
||||
* retry attempts exceed a certain threshold, while our API contract looks at the total observed
|
||||
* time of the operation (i.e. the sum of all retries).
|
||||
* @param retryTime A timeout that caps the sum of all retry attempts
|
||||
* @return A timeout that caps the timeout of the last retry attempt
|
||||
*/
|
||||
+ (NSTimeInterval)computeRetryIntervalFromRetryTime:(NSTimeInterval)retryTime;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSDictionary (FIRStorageNSDictionaryJSONHelpers)
|
||||
|
||||
/**
|
||||
* Returns a dictionary representation of the data in @a data.
|
||||
* @param data NSData containing JSON data.
|
||||
* @return An NSDictionary representation of the JSON, or nil if serialization failed.
|
||||
*/
|
||||
+ (nullable instancetype)frs_dictionaryFromJSONData:(nullable NSData *)data;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSData (FIRStorageNSDataJSONHelpers)
|
||||
|
||||
/**
|
||||
* Returns an NSData instance containing JSON serialized from @a dictionary.
|
||||
* @param dictionary An NSDictionary containing only types serializable to JSON.
|
||||
* @return An NSData object representing the binary JSON, or nil if serialization failed.
|
||||
*/
|
||||
+ (nullable instancetype)frs_dataFromJSONDictionary:(nullable NSDictionary *)dictionary;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,182 @@
|
||||
// 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 <Foundation/Foundation.h>
|
||||
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
#import <MobileCoreServices/MobileCoreServices.h>
|
||||
#elif TARGET_OS_OSX || TARGET_OS_WATCH
|
||||
#import <CoreServices/CoreServices.h>
|
||||
#endif
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageUtils.h"
|
||||
|
||||
#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageErrors.h"
|
||||
#import "FirebaseStorage/Sources/FIRStoragePath.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorageReference_Private.h"
|
||||
#import "FirebaseStorage/Sources/FIRStorage_Private.h"
|
||||
|
||||
#if SWIFT_PACKAGE
|
||||
@import GTMSessionFetcherCore;
|
||||
#else
|
||||
#import <GTMSessionFetcher/GTMSessionFetcher.h>
|
||||
#endif
|
||||
|
||||
// This is the list at https://cloud.google.com/storage/docs/json_api/ without &, ; and +.
|
||||
NSString *const kGCSObjectAllowedCharacterSet =
|
||||
@"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$'()*,=:@";
|
||||
|
||||
@implementation FIRStorageUtils
|
||||
|
||||
+ (nullable NSString *)GCSEscapedString:(NSString *)string {
|
||||
NSCharacterSet *allowedCharacters =
|
||||
[NSCharacterSet characterSetWithCharactersInString:kGCSObjectAllowedCharacterSet];
|
||||
|
||||
return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
|
||||
}
|
||||
|
||||
+ (nullable NSString *)MIMETypeForExtension:(NSString *)extension {
|
||||
if (extension == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
CFStringRef pathExtension = (__bridge_retained CFStringRef)extension;
|
||||
CFStringRef type =
|
||||
UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension, NULL);
|
||||
NSString *mimeType =
|
||||
(__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass(type, kUTTagClassMIMEType);
|
||||
CFRelease(pathExtension);
|
||||
if (type != NULL) {
|
||||
CFRelease(type);
|
||||
}
|
||||
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
+ (NSString *)queryStringForDictionary:(nullable NSDictionary *)dictionary {
|
||||
if (!dictionary) {
|
||||
return @"";
|
||||
}
|
||||
|
||||
__block NSMutableArray *queryItems = [[NSMutableArray alloc] initWithCapacity:[dictionary count]];
|
||||
[dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull name, NSString *_Nonnull value,
|
||||
BOOL *_Nonnull stop) {
|
||||
NSString *item =
|
||||
[FIRStorageUtils GCSEscapedString:[NSString stringWithFormat:@"%@=%@", name, value]];
|
||||
[queryItems addObject:item];
|
||||
}];
|
||||
return [queryItems componentsJoinedByString:@"&"];
|
||||
}
|
||||
|
||||
+ (NSURLRequest *)defaultRequestForReference:(FIRStorageReference *)reference {
|
||||
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
|
||||
NSURLComponents *components = [[NSURLComponents alloc] init];
|
||||
[components setScheme:reference.storage.scheme];
|
||||
[components setHost:reference.storage.host];
|
||||
[components setPort:reference.storage.port];
|
||||
NSString *encodedPath = [self encodedURLForPath:reference.path];
|
||||
[components setPercentEncodedPath:encodedPath];
|
||||
[request setURL:components.URL];
|
||||
return request;
|
||||
}
|
||||
|
||||
+ (NSURLRequest *)defaultRequestForReference:(FIRStorageReference *)reference
|
||||
queryParams:(NSDictionary<NSString *, NSString *> *)queryParams {
|
||||
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
|
||||
NSURLComponents *components = [[NSURLComponents alloc] init];
|
||||
[components setScheme:reference.storage.scheme];
|
||||
[components setHost:reference.storage.host];
|
||||
[components setPort:reference.storage.port];
|
||||
|
||||
NSMutableArray<NSURLQueryItem *> *queryItems = [NSMutableArray new];
|
||||
for (NSString *key in queryParams) {
|
||||
[queryItems addObject:[NSURLQueryItem queryItemWithName:key value:queryParams[key]]];
|
||||
}
|
||||
[components setQueryItems:queryItems];
|
||||
// NSURLComponents does not encode "+" as "%2B". This is however required by our backend, as
|
||||
// it treats "+" as a shorthand encoding for spaces. See also
|
||||
// https://stackoverflow.com/questions/31577188/how-to-encode-into-2b-with-nsurlcomponents
|
||||
[components setPercentEncodedQuery:[[components percentEncodedQuery]
|
||||
stringByReplacingOccurrencesOfString:@"+"
|
||||
withString:@"%2B"]];
|
||||
|
||||
NSString *encodedPath = [self encodedURLForPath:reference.path];
|
||||
[components setPercentEncodedPath:encodedPath];
|
||||
[request setURL:components.URL];
|
||||
return request;
|
||||
}
|
||||
|
||||
+ (NSString *)encodedURLForPath:(FIRStoragePath *)path {
|
||||
NSString *bucketName = [FIRStorageUtils GCSEscapedString:path.bucket];
|
||||
NSString *objectName = [FIRStorageUtils GCSEscapedString:path.object];
|
||||
NSString *bucketFormat = [NSString stringWithFormat:kFIRStorageBucketPathFormat, bucketName];
|
||||
NSString *urlPath = [@"/" stringByAppendingPathComponent:bucketFormat];
|
||||
if (objectName) {
|
||||
NSString *objectFormat = [NSString stringWithFormat:kFIRStorageObjectPathFormat, objectName];
|
||||
urlPath = [urlPath stringByAppendingFormat:@"/%@", objectFormat];
|
||||
} else {
|
||||
urlPath = [urlPath stringByAppendingString:@"/o"];
|
||||
}
|
||||
return [@"/" stringByAppendingString:[kFIRStorageVersionPath stringByAppendingString:urlPath]];
|
||||
}
|
||||
|
||||
+ (NSError *)storageErrorWithDescription:(NSString *)description code:(NSInteger)code {
|
||||
return [NSError errorWithDomain:FIRStorageErrorDomain
|
||||
code:code
|
||||
userInfo:@{NSLocalizedDescriptionKey : description}];
|
||||
}
|
||||
|
||||
+ (NSTimeInterval)computeRetryIntervalFromRetryTime:(NSTimeInterval)retryTime {
|
||||
// GTMSessionFetcher's retry starts at 1 second and then doubles every time. We use this
|
||||
// information to compute a best-effort estimate of what to translate the user provided retry
|
||||
// time into.
|
||||
|
||||
// Note that this is the same as 2 << (log2(retryTime) - 1), but deemed more readable.
|
||||
NSTimeInterval lastInterval = 1.0;
|
||||
NSTimeInterval sumOfAllIntervals = 1.0;
|
||||
|
||||
while (sumOfAllIntervals < retryTime) {
|
||||
lastInterval *= 2;
|
||||
sumOfAllIntervals += lastInterval;
|
||||
}
|
||||
|
||||
return lastInterval;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSDictionary (FIRStorageNSDictionaryJSONHelpers)
|
||||
|
||||
+ (nullable instancetype)frs_dictionaryFromJSONData:(nullable NSData *)data {
|
||||
if (!data) {
|
||||
return nil;
|
||||
}
|
||||
return [NSJSONSerialization JSONObjectWithData:data
|
||||
options:NSJSONReadingMutableContainers
|
||||
error:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSData (FIRStorageNSDataJSONHelpers)
|
||||
|
||||
+ (nullable instancetype)frs_dataFromJSONDictionary:(nullable NSDictionary *)dictionary {
|
||||
if (!dictionary) {
|
||||
return nil;
|
||||
}
|
||||
return [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@class FIRApp;
|
||||
@class GTMSessionFetcherService;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FIRStorage ()
|
||||
|
||||
@property(strong, nonatomic, readwrite) FIRApp *app;
|
||||
|
||||
@property(strong, nonatomic, nullable) GTMSessionFetcherService *fetcherServiceForApp;
|
||||
|
||||
@property(nonatomic, readonly) dispatch_queue_t dispatchQueue;
|
||||
|
||||
@property(strong, nonatomic) NSString *storageBucket;
|
||||
|
||||
@property(strong, nonatomic) NSString *scheme;
|
||||
|
||||
@property(strong, nonatomic) NSString *host;
|
||||
|
||||
@property(strong, nonatomic) NSNumber *port;
|
||||
|
||||
/**
|
||||
* Maximum time between retry attempts for uploads.
|
||||
*
|
||||
* This is used by GTMSessionFetcher and translated from the user provided `maxUploadRetryTime`.
|
||||
*/
|
||||
@property(assign, nonatomic) NSTimeInterval maxUploadRetryInterval;
|
||||
|
||||
/**
|
||||
* Maximum time between retry attempts for downloads.
|
||||
*
|
||||
* This is used by GTMSessionFetcher and translated from the user provided `maxDownloadRetryTime`.
|
||||
*/
|
||||
@property(assign, nonatomic) NSTimeInterval maxDownloadRetryInterval;
|
||||
|
||||
/**
|
||||
* Maximum time between retry attempts for any operation that is not an upload or download.
|
||||
*
|
||||
* This is used by GTMSessionFetcher and translated from the user provided `maxOperationRetryTime`.
|
||||
*/
|
||||
@property(assign, nonatomic) NSTimeInterval maxOperationRetryInterval;
|
||||
|
||||
/**
|
||||
* Enables/disables GTMSessionFetcher HTTP logging
|
||||
* @param isLoggingEnabled Boolean passed through to enable/disable GTMSessionFetcher logging
|
||||
*/
|
||||
+ (void)setGTMSessionFetcherLoggingEnabled:(BOOL)isLoggingEnabled;
|
||||
|
||||
/** Configures the storage instance. Freezes the host setting. */
|
||||
- (void)ensureConfigured;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FIRStorageConstants.h"
|
||||
|
||||
@class FIRApp;
|
||||
@class FIRStorageReference;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* FirebaseStorage is a service that supports uploading and downloading binary objects,
|
||||
* such as images, videos, and other files to Google Cloud Storage.
|
||||
*
|
||||
* If you call [FIRStorage storage], the instance will initialize with the default FIRApp,
|
||||
* [FIRApp defaultApp], and the storage location will come from the provided
|
||||
* GoogleService-Info.plist.
|
||||
*
|
||||
* If you call [FIRStorage storageForApp:] and provide a custom instance of FIRApp,
|
||||
* the storage location will be specified via the FIROptions#storageBucket property.
|
||||
*/
|
||||
NS_SWIFT_NAME(Storage)
|
||||
@interface FIRStorage : NSObject
|
||||
|
||||
/**
|
||||
* Creates an instance of FIRStorage, configured with the default FIRApp.
|
||||
* @return the FIRStorage instance, initialized with the default FIRApp.
|
||||
*/
|
||||
+ (instancetype)storage NS_SWIFT_NAME(storage());
|
||||
|
||||
/**
|
||||
* Creates an instance of FIRStorage, configured with the custom FIRApp @a app.
|
||||
* @param app The custom FIRApp used for initialization.
|
||||
* @return the FIRStorage instance, initialized with the custom FIRApp.
|
||||
*/
|
||||
+ (instancetype)storageForApp:(FIRApp *)app NS_SWIFT_NAME(storage(app:));
|
||||
|
||||
/**
|
||||
* Creates an instance of FIRStorage, configured with a custom storage bucket @a url.
|
||||
* @param url The gs:// url to your Firebase Storage Bucket.
|
||||
* @return the FIRStorage instance, initialized with the custom FIRApp.
|
||||
*/
|
||||
+ (instancetype)storageWithURL:(NSString *)url NS_SWIFT_NAME(storage(url:));
|
||||
|
||||
/**
|
||||
* Creates an instance of FIRStorage, configured with a custom FIRApp @a app and a custom storage
|
||||
* bucket @a url.
|
||||
* @param app The custom FIRApp used for initialization.
|
||||
* @param url The gs:// url to your Firebase Storage Bucket.
|
||||
* @return the FIRStorage instance, initialized with the custom FIRApp.
|
||||
*/
|
||||
+ (instancetype)storageForApp:(FIRApp *)app URL:(NSString *)url NS_SWIFT_NAME(storage(app:url:));
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* The Firebase App associated with this Firebase Storage instance.
|
||||
*/
|
||||
@property(strong, nonatomic, readonly) FIRApp *app;
|
||||
|
||||
/**
|
||||
* Maximum time in seconds to retry an upload if a failure occurs.
|
||||
* Defaults to 10 minutes (600 seconds).
|
||||
*/
|
||||
@property NSTimeInterval maxUploadRetryTime;
|
||||
|
||||
/**
|
||||
* Maximum time in seconds to retry a download if a failure occurs.
|
||||
* Defaults to 10 minutes (600 seconds).
|
||||
*/
|
||||
@property NSTimeInterval maxDownloadRetryTime;
|
||||
|
||||
/**
|
||||
* Maximum time in seconds to retry operations other than upload and download if a failure occurs.
|
||||
* Defaults to 2 minutes (120 seconds).
|
||||
*/
|
||||
@property NSTimeInterval maxOperationRetryTime;
|
||||
|
||||
/**
|
||||
* Queue that all developer callbacks are fired on. Defaults to the main queue.
|
||||
*/
|
||||
@property(strong, nonatomic) dispatch_queue_t callbackQueue;
|
||||
|
||||
/**
|
||||
* Creates a FIRStorageReference initialized at the root Firebase Storage location.
|
||||
* @return An instance of FIRStorageReference initialized at the root.
|
||||
*/
|
||||
- (FIRStorageReference *)reference;
|
||||
|
||||
/**
|
||||
* Creates a FIRStorageReference given a gs:// or https:// URL pointing to a Firebase Storage
|
||||
* location. For example, you can pass in an https:// download URL retrieved from
|
||||
* [FIRStorageReference downloadURLWithCompletion] or the gs:// URI from
|
||||
* [FIRStorageReference description].
|
||||
* @param string A gs:// or https:// URL to initialize the reference with.
|
||||
* @return An instance of FIRStorageReference at the given child path.
|
||||
* @throws Throws an exception if passed in URL is not associated with the FIRApp used to initialize
|
||||
* this FIRStorage.
|
||||
*/
|
||||
- (FIRStorageReference *)referenceForURL:(NSString *)string;
|
||||
|
||||
/**
|
||||
* Creates a FIRStorageReference initialized at a child Firebase Storage location.
|
||||
* @param string A relative path from the root to initialize the reference with,
|
||||
* for instance @"path/to/object".
|
||||
* @return An instance of FIRStorageReference at the given child path.
|
||||
*/
|
||||
- (FIRStorageReference *)referenceWithPath:(NSString *)string;
|
||||
|
||||
/**
|
||||
* Configures the Storage SDK to use an emulated backend instead of the default remote backend.
|
||||
*/
|
||||
- (void)useEmulatorWithHost:(NSString *)host port:(NSInteger)port;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
@class FIRStorageDownloadTask;
|
||||
@class FIRStorageMetadata;
|
||||
@class FIRStorageTaskSnapshot;
|
||||
@class FIRStorageUploadTask;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* NSString typedef representing a task listener handle.
|
||||
*/
|
||||
typedef NSString *FIRStorageHandle NS_SWIFT_NAME(StorageHandle);
|
||||
|
||||
/**
|
||||
* Block typedef typically used when downloading data.
|
||||
* @param data The data returned by the download, or nil if no data available or download failed.
|
||||
* @param error The error describing failure, if one occurred.
|
||||
*/
|
||||
typedef void (^FIRStorageVoidDataError)(NSData *_Nullable data, NSError *_Nullable error)
|
||||
NS_SWIFT_NAME(StorageVoidDataError);
|
||||
|
||||
/**
|
||||
* Block typedef typically used when performing "binary" async operations such as delete,
|
||||
* where the operation either succeeds without an error or fails with an error.
|
||||
* @param error The error describing failure, if one occurred.
|
||||
*/
|
||||
typedef void (^FIRStorageVoidError)(NSError *_Nullable error) NS_SWIFT_NAME(StorageVoidError);
|
||||
|
||||
/**
|
||||
* Block typedef typically used when retrieving metadata.
|
||||
* @param metadata The metadata returned by the operation, if metadata exists.
|
||||
*/
|
||||
typedef void (^FIRStorageVoidMetadata)(FIRStorageMetadata *_Nullable metadata)
|
||||
NS_SWIFT_NAME(StorageVoidMetadata);
|
||||
|
||||
/**
|
||||
* Block typedef typically used when retrieving metadata with the possibility of an error.
|
||||
* @param metadata The metadata returned by the operation, if metadata exists.
|
||||
* @param error The error describing failure, if one occurred.
|
||||
*/
|
||||
typedef void (^FIRStorageVoidMetadataError)(FIRStorageMetadata *_Nullable metadata,
|
||||
NSError *_Nullable error)
|
||||
NS_SWIFT_NAME(StorageVoidMetadataError);
|
||||
|
||||
/**
|
||||
* Block typedef typically used to asynchronously return a storage task snapshot.
|
||||
* @param snapshot The returned task snapshot.
|
||||
*/
|
||||
typedef void (^FIRStorageVoidSnapshot)(FIRStorageTaskSnapshot *snapshot)
|
||||
NS_SWIFT_NAME(StorageVoidSnapshot);
|
||||
|
||||
/**
|
||||
* Block typedef typically used when retrieving a download URL.
|
||||
* @param URL The download URL associated with the operation.
|
||||
* @param error The error describing failure, if one occurred.
|
||||
*/
|
||||
typedef void (^FIRStorageVoidURLError)(NSURL *_Nullable URL, NSError *_Nullable error)
|
||||
NS_SWIFT_NAME(StorageVoidURLError);
|
||||
|
||||
/**
|
||||
* Enum representing the upload and download task status.
|
||||
*/
|
||||
typedef NS_ENUM(NSInteger, FIRStorageTaskStatus) {
|
||||
/**
|
||||
* Unknown task status.
|
||||
*/
|
||||
FIRStorageTaskStatusUnknown,
|
||||
|
||||
/**
|
||||
* Task is being resumed.
|
||||
*/
|
||||
FIRStorageTaskStatusResume,
|
||||
|
||||
/**
|
||||
* Task reported a progress event.
|
||||
*/
|
||||
FIRStorageTaskStatusProgress,
|
||||
|
||||
/**
|
||||
* Task is paused.
|
||||
*/
|
||||
FIRStorageTaskStatusPause,
|
||||
|
||||
/**
|
||||
* Task has completed successfully.
|
||||
*/
|
||||
FIRStorageTaskStatusSuccess,
|
||||
|
||||
/**
|
||||
* Task has failed and is unrecoverable.
|
||||
*/
|
||||
FIRStorageTaskStatusFailure
|
||||
} NS_SWIFT_NAME(StorageTaskStatus);
|
||||
|
||||
/**
|
||||
* Firebase Storage error domain.
|
||||
*/
|
||||
FOUNDATION_EXPORT NSString *const FIRStorageErrorDomain NS_SWIFT_NAME(StorageErrorDomain);
|
||||
|
||||
/**
|
||||
* Enum representing the errors raised by Firebase Storage.
|
||||
*/
|
||||
typedef NS_ENUM(NSInteger, FIRStorageErrorCode) {
|
||||
/** An unknown error occurred. */
|
||||
FIRStorageErrorCodeUnknown = -13000,
|
||||
|
||||
/** No object exists at the desired reference. */
|
||||
FIRStorageErrorCodeObjectNotFound = -13010,
|
||||
|
||||
/** No bucket is configured for Firebase Storage. */
|
||||
FIRStorageErrorCodeBucketNotFound = -13011,
|
||||
|
||||
/** No project is configured for Firebase Storage. */
|
||||
FIRStorageErrorCodeProjectNotFound = -13012,
|
||||
|
||||
/**
|
||||
* Quota on your Firebase Storage bucket has been exceeded.
|
||||
* If you're on the free tier, upgrade to a paid plan.
|
||||
* If you're on a paid plan, reach out to Firebase support.
|
||||
*/
|
||||
FIRStorageErrorCodeQuotaExceeded = -13013,
|
||||
|
||||
/** User is unauthenticated. Authenticate and try again. */
|
||||
FIRStorageErrorCodeUnauthenticated = -13020,
|
||||
|
||||
/**
|
||||
* User is not authorized to perform the desired action.
|
||||
* Check your rules to ensure they are correct.
|
||||
*/
|
||||
FIRStorageErrorCodeUnauthorized = -13021,
|
||||
|
||||
/**
|
||||
* The maximum time limit on an operation (upload, download, delete, etc.) has been exceeded.
|
||||
* Try uploading again.
|
||||
*/
|
||||
FIRStorageErrorCodeRetryLimitExceeded = -13030,
|
||||
|
||||
/**
|
||||
* File on the client does not match the checksum of the file received by the server.
|
||||
* Try uploading again.
|
||||
*/
|
||||
FIRStorageErrorCodeNonMatchingChecksum = -13031,
|
||||
|
||||
/**
|
||||
* Size of the downloaded file exceeds the amount of memory allocated for the download.
|
||||
* Increase memory cap and try downloading again.
|
||||
*/
|
||||
FIRStorageErrorCodeDownloadSizeExceeded = -13032,
|
||||
|
||||
/** User cancelled the operation. */
|
||||
FIRStorageErrorCodeCancelled = -13040,
|
||||
|
||||
/** An invalid argument was provided. */
|
||||
FIRStorageErrorCodeInvalidArgument = -13050
|
||||
} NS_SWIFT_NAME(StorageErrorCode);
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FIRStorageObservableTask.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* FIRStorageDownloadTask implements resumable downloads from an object in Firebase Storage.
|
||||
* Downloads can be returned on completion with a completion handler, and can be monitored
|
||||
* by attaching observers, or controlled by calling FIRStorageTask#pause, FIRStorageTask#resume,
|
||||
* or FIRStorageTask#cancel.
|
||||
* Downloads can currently be returned as NSData in memory, or as an NSURL to a file on disk.
|
||||
* Downloads are performed on a background queue, and callbacks are raised on the developer
|
||||
* specified callbackQueue in FIRStorage, or the main queue if left unspecified.
|
||||
* Currently all uploads must be initiated and managed on the main queue.
|
||||
*/
|
||||
NS_SWIFT_NAME(StorageDownloadTask)
|
||||
@interface FIRStorageDownloadTask : FIRStorageObservableTask <FIRStorageTaskManagement>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2019 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 <Foundation/Foundation.h>
|
||||
|
||||
@class FIRStorageReference;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** Contains the prefixes and items returned by a `StorageReference.list()` call. */
|
||||
NS_SWIFT_NAME(StorageListResult)
|
||||
@interface FIRStorageListResult : NSObject <NSCopying>
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* The prefixes (folders) returned by the `list()` operation.
|
||||
*
|
||||
* @return A list of prefixes (folders).
|
||||
*/
|
||||
@property(nonatomic, readonly) NSArray<FIRStorageReference *> *prefixes;
|
||||
|
||||
/**
|
||||
* The items (files) returned by the `list()` operation.
|
||||
*
|
||||
* @return A list of items (files).
|
||||
*/
|
||||
@property(nonatomic, readonly) NSArray<FIRStorageReference *> *items;
|
||||
|
||||
/**
|
||||
* Returns a token that can be used to resume a previous `list()` operation. `nil`
|
||||
* indicates that there are no more results.
|
||||
*
|
||||
* @return A page token if more results are available.
|
||||
*/
|
||||
@property(nonatomic, readonly, nullable) NSString *pageToken;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
@class FIRStorageReference;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* Class which represents the metadata on an object in Firebase Storage. This metadata is
|
||||
* returned on successful operations, and can be used to retrieve download URLs, content types,
|
||||
* and a FIRStorage reference to the object in question. Full documentation can be found at the GCS
|
||||
* Objects#resource docs.
|
||||
* @see https://cloud.google.com/storage/docs/json_api/v1/objects#resource
|
||||
*/
|
||||
NS_SWIFT_NAME(StorageMetadata)
|
||||
@interface FIRStorageMetadata : NSObject <NSCopying>
|
||||
|
||||
/**
|
||||
* The name of the bucket containing this object.
|
||||
*/
|
||||
@property(copy, nonatomic, readonly) NSString *bucket;
|
||||
|
||||
/**
|
||||
* Cache-Control directive for the object data.
|
||||
*/
|
||||
@property(copy, nonatomic, nullable) NSString *cacheControl;
|
||||
|
||||
/**
|
||||
* Content-Disposition of the object data.
|
||||
*/
|
||||
@property(copy, nonatomic, nullable) NSString *contentDisposition;
|
||||
|
||||
/**
|
||||
* Content-Encoding of the object data.
|
||||
*/
|
||||
@property(copy, nonatomic, nullable) NSString *contentEncoding;
|
||||
|
||||
/**
|
||||
* Content-Language of the object data.
|
||||
*/
|
||||
@property(copy, nonatomic, nullable) NSString *contentLanguage;
|
||||
|
||||
/**
|
||||
* Content-Type of the object data.
|
||||
*/
|
||||
@property(copy, nonatomic, nullable) NSString *contentType;
|
||||
|
||||
/**
|
||||
* MD5 hash of the data; encoded using base64.
|
||||
*/
|
||||
@property(copy, nonatomic, nullable, readonly) NSString *md5Hash;
|
||||
|
||||
/**
|
||||
* The content generation of this object. Used for object versioning.
|
||||
*/
|
||||
@property(readonly) int64_t generation;
|
||||
|
||||
/**
|
||||
* User-provided metadata, in key/value pairs.
|
||||
*/
|
||||
@property(copy, nonatomic, nullable) NSDictionary<NSString *, NSString *> *customMetadata;
|
||||
|
||||
/**
|
||||
* The version of the metadata for this object at this generation. Used
|
||||
* for preconditions and for detecting changes in metadata. A metageneration number is only
|
||||
* meaningful in the context of a particular generation of a particular object.
|
||||
*/
|
||||
@property(readonly) int64_t metageneration;
|
||||
|
||||
/**
|
||||
* The name of this object, in gs://bucket/path/to/object.txt, this is object.txt.
|
||||
*/
|
||||
@property(copy, nonatomic, readonly, nullable) NSString *name;
|
||||
|
||||
/**
|
||||
* The full path of this object, in gs://bucket/path/to/object.txt, this is path/to/object.txt.
|
||||
*/
|
||||
@property(copy, nonatomic, readonly, nullable) NSString *path;
|
||||
|
||||
/**
|
||||
* Content-Length of the data in bytes.
|
||||
*/
|
||||
@property(readonly) int64_t size;
|
||||
|
||||
/**
|
||||
* The creation time of the object in RFC 3339 format.
|
||||
*/
|
||||
@property(copy, nonatomic, readonly, nullable) NSDate *timeCreated;
|
||||
|
||||
/**
|
||||
* The modification time of the object metadata in RFC 3339 format.
|
||||
*/
|
||||
@property(copy, nonatomic, readonly, nullable) NSDate *updated;
|
||||
|
||||
/**
|
||||
* A reference to the object in Firebase Storage.
|
||||
*/
|
||||
@property(strong, nonatomic, readonly, nullable) FIRStorageReference *storageReference;
|
||||
|
||||
/**
|
||||
* Creates an instance of FIRStorageMetadata from the contents of a dictionary.
|
||||
* @return An instance of FIRStorageMetadata that represents the contents of a dictionary.
|
||||
*/
|
||||
- (nullable instancetype)initWithDictionary:(NSDictionary<NSString *, id> *)dictionary
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Creates an NSDictionary from the contents of the metadata.
|
||||
* @return An NSDictionary that represents the contents of the metadata.
|
||||
*/
|
||||
- (NSDictionary<NSString *, id> *)dictionaryRepresentation;
|
||||
|
||||
/**
|
||||
* Determines if the current metadata represents a "file".
|
||||
*/
|
||||
@property(readonly, getter=isFile) BOOL file;
|
||||
|
||||
/**
|
||||
* Determines if the current metadata represents a "folder".
|
||||
*/
|
||||
@property(readonly, getter=isFolder) BOOL folder;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 "FIRStorageTask.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class FIRStorageReference;
|
||||
@class FIRStorageTaskSnapshot;
|
||||
|
||||
/**
|
||||
* Extends FIRStorageTask to provide observable semantics such as adding and removing observers.
|
||||
* Observers produce a FIRStorageHandle, which is used to keep track of and remove specific
|
||||
* observers at a later date.
|
||||
* This class is currently not thread safe and can only be called on the main thread.
|
||||
*/
|
||||
NS_SWIFT_NAME(StorageObservableTask)
|
||||
@interface FIRStorageObservableTask : FIRStorageTask
|
||||
|
||||
/**
|
||||
* Observes changes in the upload status: Resume, Pause, Progress, Success, and Failure.
|
||||
* @param status The FIRStorageTaskStatus change to observe.
|
||||
* @param handler A callback that fires every time the status event occurs,
|
||||
* returns a FIRStorageTaskSnapshot containing the state of the task.
|
||||
* @return A task handle that can be used to remove the observer at a later date.
|
||||
*/
|
||||
- (FIRStorageHandle)observeStatus:(FIRStorageTaskStatus)status
|
||||
handler:(void (^)(FIRStorageTaskSnapshot *snapshot))handler;
|
||||
|
||||
/**
|
||||
* Removes the single observer with the provided handle.
|
||||
* @param handle The handle of the task to remove.
|
||||
*/
|
||||
- (void)removeObserverWithHandle:(FIRStorageHandle)handle;
|
||||
|
||||
/**
|
||||
* Removes all observers for a single status.
|
||||
* @param status A FIRStorageTaskStatus to remove listeners for.
|
||||
*/
|
||||
- (void)removeAllObserversForStatus:(FIRStorageTaskStatus)status;
|
||||
|
||||
/**
|
||||
* Removes all observers.
|
||||
*/
|
||||
- (void)removeAllObservers;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+315
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FIRStorage.h"
|
||||
#import "FIRStorageConstants.h"
|
||||
#import "FIRStorageDownloadTask.h"
|
||||
#import "FIRStorageListResult.h"
|
||||
#import "FIRStorageMetadata.h"
|
||||
#import "FIRStorageTask.h"
|
||||
#import "FIRStorageUploadTask.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* FIRStorageReference represents a reference to a Google Cloud Storage object. Developers can
|
||||
* upload and download objects, as well as get/set object metadata, and delete an object at the
|
||||
* path.
|
||||
* @see https://cloud.google.com/storage/
|
||||
*/
|
||||
NS_SWIFT_NAME(StorageReference)
|
||||
@interface FIRStorageReference : NSObject
|
||||
|
||||
/**
|
||||
* The FIRStorage service object which created this reference.
|
||||
*/
|
||||
@property(nonatomic, readonly) FIRStorage *storage;
|
||||
|
||||
/**
|
||||
* The name of the Google Cloud Storage bucket associated with this reference,
|
||||
* in gs://bucket/path/to/object.txt, the bucket would be: 'bucket'
|
||||
*/
|
||||
@property(nonatomic, readonly) NSString *bucket;
|
||||
|
||||
/**
|
||||
* The full path to this object, not including the Google Cloud Storage bucket.
|
||||
* In gs://bucket/path/to/object.txt, the full path would be: 'path/to/object.txt'
|
||||
*/
|
||||
@property(nonatomic, readonly) NSString *fullPath;
|
||||
|
||||
/**
|
||||
* The short name of the object associated with this reference,
|
||||
* in gs://bucket/path/to/object.txt, the name of the object would be: 'object.txt'
|
||||
*/
|
||||
@property(nonatomic, readonly) NSString *name;
|
||||
|
||||
#pragma mark - Path Operations
|
||||
|
||||
/**
|
||||
* Creates a new FIRStorageReference pointing to the root object.
|
||||
* @return A new FIRStorageReference pointing to the root object.
|
||||
*/
|
||||
- (FIRStorageReference *)root;
|
||||
|
||||
/**
|
||||
* Creates a new FIRStorageReference pointing to the parent of the current reference
|
||||
* or nil if this instance references the root location.
|
||||
* For example:
|
||||
* path = foo/bar/baz parent = foo/bar
|
||||
* path = foo parent = (root)
|
||||
* path = (root) parent = nil
|
||||
* @return A new FIRStorageReference pointing to the parent of the current reference.
|
||||
*/
|
||||
- (nullable FIRStorageReference *)parent;
|
||||
|
||||
/**
|
||||
* Creates a new FIRStorageReference pointing to a child object of the current reference.
|
||||
* path = foo child = bar newPath = foo/bar
|
||||
* path = foo/bar child = baz newPath = foo/bar/baz
|
||||
* All leading and trailing slashes will be removed, and consecutive slashes will be
|
||||
* compressed to single slashes. For example:
|
||||
* child = /foo/bar newPath = foo/bar
|
||||
* child = foo/bar/ newPath = foo/bar
|
||||
* child = foo///bar newPath = foo/bar
|
||||
* @param path Path to append to the current path.
|
||||
* @return A new FIRStorageReference pointing to a child location of the current reference.
|
||||
*/
|
||||
- (FIRStorageReference *)child:(NSString *)path;
|
||||
|
||||
#pragma mark - Uploads
|
||||
|
||||
/**
|
||||
* Asynchronously uploads data to the currently specified FIRStorageReference,
|
||||
* without additional metadata.
|
||||
* This is not recommended for large files, and one should instead upload a file from disk.
|
||||
* @param uploadData The NSData to upload.
|
||||
* @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload.
|
||||
*/
|
||||
- (FIRStorageUploadTask *)putData:(NSData *)uploadData NS_SWIFT_NAME(putData(_:));
|
||||
|
||||
/**
|
||||
* Asynchronously uploads data to the currently specified FIRStorageReference.
|
||||
* This is not recommended for large files, and one should instead upload a file from disk.
|
||||
* @param uploadData The NSData to upload.
|
||||
* @param metadata FIRStorageMetadata containing additional information (MIME type, etc.)
|
||||
* about the object being uploaded.
|
||||
* @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload.
|
||||
*/
|
||||
// clang-format off
|
||||
- (FIRStorageUploadTask *)putData:(NSData *)uploadData
|
||||
metadata:(nullable FIRStorageMetadata *)metadata
|
||||
NS_SWIFT_NAME(putData(_:metadata:));
|
||||
// clang-format on
|
||||
|
||||
/**
|
||||
* Asynchronously uploads data to the currently specified FIRStorageReference.
|
||||
* This is not recommended for large files, and one should instead upload a file from disk.
|
||||
* @param uploadData The NSData to upload.
|
||||
* @param metadata FIRStorageMetadata containing additional information (MIME type, etc.)
|
||||
* about the object being uploaded.
|
||||
* @param completion A completion block that either returns the object metadata on success,
|
||||
* or an error on failure.
|
||||
* @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload.
|
||||
*/
|
||||
// clang-format off
|
||||
- (FIRStorageUploadTask *)putData:(NSData *)uploadData
|
||||
metadata:(nullable FIRStorageMetadata *)metadata
|
||||
completion:(nullable void (^)(FIRStorageMetadata *_Nullable metadata,
|
||||
NSError *_Nullable error))completion
|
||||
NS_SWIFT_NAME(putData(_:metadata:completion:));
|
||||
// clang-format on
|
||||
|
||||
/**
|
||||
* Asynchronously uploads a file to the currently specified FIRStorageReference,
|
||||
* without additional metadata.
|
||||
* @param fileURL A URL representing the system file path of the object to be uploaded.
|
||||
* @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload.
|
||||
*/
|
||||
- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL NS_SWIFT_NAME(putFile(from:));
|
||||
|
||||
/**
|
||||
* Asynchronously uploads a file to the currently specified FIRStorageReference.
|
||||
* @param fileURL A URL representing the system file path of the object to be uploaded.
|
||||
* @param metadata FIRStorageMetadata containing additional information (MIME type, etc.)
|
||||
* about the object being uploaded.
|
||||
* @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload.
|
||||
*/
|
||||
// clang-format off
|
||||
- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL
|
||||
metadata:(nullable FIRStorageMetadata *)metadata
|
||||
NS_SWIFT_NAME(putFile(from:metadata:));
|
||||
// clang-format on
|
||||
|
||||
/**
|
||||
* Asynchronously uploads a file to the currently specified FIRStorageReference.
|
||||
* @param fileURL A URL representing the system file path of the object to be uploaded.
|
||||
* @param metadata FIRStorageMetadata containing additional information (MIME type, etc.)
|
||||
* about the object being uploaded.
|
||||
* @param completion A completion block that either returns the object metadata on success,
|
||||
* or an error on failure.
|
||||
* @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload.
|
||||
*/
|
||||
// clang-format off
|
||||
- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL
|
||||
metadata:(nullable FIRStorageMetadata *)metadata
|
||||
completion:(nullable void (^)(FIRStorageMetadata *_Nullable metadata,
|
||||
NSError *_Nullable error))completion
|
||||
NS_SWIFT_NAME(putFile(from:metadata:completion:));
|
||||
// clang-format on
|
||||
|
||||
#pragma mark - Downloads
|
||||
|
||||
/**
|
||||
* Asynchronously downloads the object at the FIRStorageReference to an NSData object in memory.
|
||||
* An NSData of the provided max size will be allocated, so ensure that the device has enough free
|
||||
* memory to complete the download. For downloading large files, writeToFile may be a better option.
|
||||
* @param size The maximum size in bytes to download. If the download exceeds this size,
|
||||
* the task will be cancelled and an error will be returned.
|
||||
* @param completion A completion block that either returns the object data on success,
|
||||
* or an error on failure.
|
||||
* @return An FIRStorageDownloadTask that can be used to monitor or manage the download.
|
||||
*/
|
||||
// clang-format off
|
||||
- (FIRStorageDownloadTask *)dataWithMaxSize:(int64_t)size
|
||||
completion:(void (^)(NSData *_Nullable data,
|
||||
NSError *_Nullable error))completion
|
||||
NS_SWIFT_NAME(getData(maxSize:completion:));
|
||||
// clang-format on
|
||||
|
||||
/**
|
||||
* Asynchronously retrieves a long lived download URL with a revokable token.
|
||||
* This can be used to share the file with others, but can be revoked by a developer
|
||||
* in the Firebase Console.
|
||||
* @param completion A completion block that either returns the URL on success,
|
||||
* or an error on failure.
|
||||
*/
|
||||
- (void)downloadURLWithCompletion:(void (^)(NSURL *_Nullable URL,
|
||||
NSError *_Nullable error))completion;
|
||||
|
||||
/**
|
||||
* Asynchronously downloads the object at the current path to a specified system filepath.
|
||||
* @param fileURL A file system URL representing the path the object should be downloaded to.
|
||||
* @return An FIRStorageDownloadTask that can be used to monitor or manage the download.
|
||||
*/
|
||||
- (FIRStorageDownloadTask *)writeToFile:(NSURL *)fileURL;
|
||||
|
||||
/**
|
||||
* Asynchronously downloads the object at the current path to a specified system filepath.
|
||||
* @param fileURL A file system URL representing the path the object should be downloaded to.
|
||||
* @param completion A completion block that fires when the file download completes.
|
||||
* Returns an NSURL pointing to the file path of the downloaded file on success,
|
||||
* or an error on failure.
|
||||
* @return An FIRStorageDownloadTask that can be used to monitor or manage the download.
|
||||
*/
|
||||
- (FIRStorageDownloadTask *)writeToFile:(NSURL *)fileURL
|
||||
completion:(nullable void (^)(NSURL *_Nullable URL,
|
||||
NSError *_Nullable error))completion;
|
||||
#pragma mark - List Support
|
||||
|
||||
/**
|
||||
* List all items (files) and prefixes (folders) under this StorageReference.
|
||||
*
|
||||
* This is a helper method for calling list() repeatedly until there are no more results.
|
||||
* Consistency of the result is not guaranteed if objects are inserted or removed while this
|
||||
* operation is executing. All results are buffered in memory.
|
||||
*
|
||||
* `listAll(completion:)` is only available for projects using Firebase Rules Version 2.
|
||||
*
|
||||
* @param completion A completion handler that will be invoked with all items and prefixes under
|
||||
* the current StorageReference.
|
||||
*/
|
||||
- (void)listAllWithCompletion:(void (^)(FIRStorageListResult *result,
|
||||
NSError *_Nullable error))completion;
|
||||
|
||||
/**
|
||||
* List up to `maxResults` items (files) and prefixes (folders) under this StorageReference.
|
||||
*
|
||||
* "/" is treated as a path delimiter. Firebase Storage does not support unsupported object
|
||||
* paths that end with "/" or contain two consecutive "/"s. All invalid objects in GCS will be
|
||||
* filtered.
|
||||
*
|
||||
* `list(maxResults:completion:)` is only available for projects using Firebase Rules Version 2.
|
||||
*
|
||||
* @param maxResults The maximum number of results to return in a single page. Must be greater
|
||||
* than 0 and at most 1000.
|
||||
* @param completion A completion handler that will be invoked with up to maxResults items and
|
||||
* prefixes under the current StorageReference.
|
||||
*/
|
||||
- (void)listWithMaxResults:(int64_t)maxResults
|
||||
completion:
|
||||
(void (^)(FIRStorageListResult *result, NSError *_Nullable error))completion
|
||||
NS_SWIFT_NAME(list(maxResults:completion:));
|
||||
|
||||
/**
|
||||
* Resumes a previous call to list(maxResults:completion:)`, starting after a pagination token.
|
||||
* Returns the next set of items (files) and prefixes (folders) under this StorageReference.
|
||||
*
|
||||
* "/" is treated as a path delimiter. Firebase Storage does not support unsupported object
|
||||
* paths that end with "/" or contain two consecutive "/"s. All invalid objects in GCS will be
|
||||
* filtered.
|
||||
*
|
||||
* `list(maxResults:pageToken:completion:)`is only available for projects using Firebase Rules
|
||||
* Version 2.
|
||||
*
|
||||
* @param maxResults The maximum number of results to return in a single page. Must be greater
|
||||
* than 0 and at most 1000.
|
||||
* @param pageToken A page token from a previous call to list.
|
||||
* @param completion A completion handler that will be invoked with the next items and prefixes
|
||||
* under the current StorageReference.
|
||||
*/
|
||||
- (void)listWithMaxResults:(int64_t)maxResults
|
||||
pageToken:(NSString *)pageToken
|
||||
completion:
|
||||
(void (^)(FIRStorageListResult *result, NSError *_Nullable error))completion
|
||||
NS_SWIFT_NAME(list(maxResults:pageToken:completion:));
|
||||
|
||||
#pragma mark - Metadata Operations
|
||||
|
||||
/**
|
||||
* Retrieves metadata associated with an object at the current path.
|
||||
* @param completion A completion block which returns the object metadata on success,
|
||||
* or an error on failure.
|
||||
*/
|
||||
- (void)metadataWithCompletion:
|
||||
(void (^)(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error))completion
|
||||
NS_SWIFT_NAME(getMetadata(completion:));
|
||||
|
||||
/**
|
||||
* Updates the metadata associated with an object at the current path.
|
||||
* @param metadata An FIRStorageMetadata object with the metadata to update.
|
||||
* @param completion A completion block which returns the FIRStorageMetadata on success,
|
||||
* or an error on failure.
|
||||
*/
|
||||
// clang-format off
|
||||
- (void)updateMetadata:(FIRStorageMetadata *)metadata
|
||||
completion:(nullable void (^)(FIRStorageMetadata *_Nullable metadata,
|
||||
NSError *_Nullable error))completion
|
||||
NS_SWIFT_NAME(updateMetadata(_:completion:));
|
||||
// clang-format on
|
||||
|
||||
#pragma mark - Delete
|
||||
|
||||
/**
|
||||
* Deletes the object at the current path.
|
||||
* @param completion A completion block which returns nil on success, or an error on failure.
|
||||
*/
|
||||
- (void)deleteWithCompletion:(nullable void (^)(NSError *_Nullable error))completion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FIRStorageConstants.h"
|
||||
#import "FIRStorageMetadata.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* A superclass to all FIRStorage*Tasks, including FIRStorageUploadTask
|
||||
* and FIRStorageDownloadTask, to provide state transitions, event raising, and common storage
|
||||
* or metadata and errors.
|
||||
* Callbacks are always fired on the developer specified callback queue.
|
||||
* If no queue is specified by the developer, it defaults to the main queue.
|
||||
* Currently not thread safe, so only call methods on the main thread.
|
||||
*/
|
||||
NS_SWIFT_NAME(StorageTask)
|
||||
@interface FIRStorageTask : NSObject
|
||||
|
||||
/**
|
||||
* An immutable view of the task and associated metadata, progress, error, etc.
|
||||
*/
|
||||
@property(strong, readonly, nonatomic, nonnull) FIRStorageTaskSnapshot *snapshot;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* Defines task operations such as pause, resume, cancel, and enqueue for all tasks.
|
||||
* All tasks are required to implement enqueue, which begins the task, and may optionally
|
||||
* implement pause, resume, and cancel, which operate on the task to pause, resume, and cancel
|
||||
* operations.
|
||||
*/
|
||||
NS_SWIFT_NAME(StorageTaskManagement)
|
||||
@protocol FIRStorageTaskManagement <NSObject>
|
||||
|
||||
@required
|
||||
/**
|
||||
* Prepares a task and begins execution.
|
||||
*/
|
||||
- (void)enqueue;
|
||||
|
||||
@optional
|
||||
/**
|
||||
* Pauses a task currently in progress.
|
||||
*/
|
||||
- (void)pause;
|
||||
|
||||
/**
|
||||
* Cancels a task currently in progress.
|
||||
*/
|
||||
- (void)cancel;
|
||||
|
||||
/**
|
||||
* Resumes a task that is paused.
|
||||
*/
|
||||
- (void)resume;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FIRStorageConstants.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class FIRStorageMetadata;
|
||||
@class FIRStorageReference;
|
||||
@class FIRStorageTask;
|
||||
|
||||
/**
|
||||
* FIRStorageTaskSnapshot represents an immutable view of a task.
|
||||
* A Snapshot contains a task, storage reference, metadata (if it exists),
|
||||
* progress, and an error (if one occurred).
|
||||
*/
|
||||
NS_SWIFT_NAME(StorageTaskSnapshot)
|
||||
@interface FIRStorageTaskSnapshot : NSObject
|
||||
|
||||
/**
|
||||
* Subclass of FIRStorageTask this snapshot represents.
|
||||
*/
|
||||
@property(readonly, copy, nonatomic) __kindof FIRStorageTask *task;
|
||||
|
||||
/**
|
||||
* Metadata returned by the task, or nil if no metadata returned.
|
||||
*/
|
||||
@property(readonly, copy, nonatomic, nullable) FIRStorageMetadata *metadata;
|
||||
|
||||
/**
|
||||
* FIRStorageReference this task is operates on.
|
||||
*/
|
||||
@property(readonly, copy, nonatomic) FIRStorageReference *reference;
|
||||
|
||||
/**
|
||||
* NSProgress object which tracks the progress of an upload or download.
|
||||
*/
|
||||
@property(readonly, strong, nonatomic, nullable) NSProgress *progress;
|
||||
|
||||
/**
|
||||
* Error during task execution, or nil if no error occurred.
|
||||
*/
|
||||
@property(readonly, copy, nonatomic, nullable) NSError *error;
|
||||
|
||||
/**
|
||||
* Status of the task.
|
||||
*/
|
||||
@property(readonly, nonatomic) FIRStorageTaskStatus status;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FIRStorageObservableTask.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* FIRStorageUploadTask implements resumable uploads to a file in Firebase Storage.
|
||||
* Uploads can be returned on completion with a completion callback, and can be monitored
|
||||
* by attaching observers, or controlled by calling FIRStorageTask#pause, FIRStorageTask#resume,
|
||||
* or FIRStorageTask#cancel.
|
||||
* Uploads can take NSData in memory, or an NSURL to a file on disk.
|
||||
* Uploads are performed on a background queue, and callbacks are raised on the developer
|
||||
* specified callbackQueue in FIRStorage, or the main queue if left unspecified.
|
||||
* Currently all uploads must be initiated and managed on the main queue.
|
||||
*/
|
||||
NS_SWIFT_NAME(StorageUploadTask)
|
||||
@interface FIRStorageUploadTask : FIRStorageObservableTask <FIRStorageTaskManagement>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.h"
|
||||
#import "FIRStorageDownloadTask.h"
|
||||
#import "FIRStorageListResult.h"
|
||||
#import "FIRStorageMetadata.h"
|
||||
#import "FIRStorageObservableTask.h"
|
||||
#import "FIRStorageReference.h"
|
||||
#import "FIRStorageTask.h"
|
||||
#import "FIRStorageTaskSnapshot.h"
|
||||
#import "FIRStorageUploadTask.h"
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef FIRAuthInterop_h
|
||||
#define FIRAuthInterop_h
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** @typedef FIRTokenCallback
|
||||
@brief The type of block which gets called when a token is ready.
|
||||
*/
|
||||
typedef void (^FIRTokenCallback)(NSString *_Nullable token, NSError *_Nullable error)
|
||||
NS_SWIFT_NAME(TokenCallback);
|
||||
|
||||
/// Common methods for Auth interoperability.
|
||||
NS_SWIFT_NAME(AuthInterop)
|
||||
@protocol FIRAuthInterop
|
||||
|
||||
/// Retrieves the Firebase authentication token, possibly refreshing it if it has expired.
|
||||
- (void)getTokenForcingRefresh:(BOOL)forceRefresh withCallback:(FIRTokenCallback)callback;
|
||||
|
||||
/// Get the current Auth user's UID. Returns nil if there is no user signed in.
|
||||
- (nullable NSString *)getUserID;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif /* FIRAuthInterop_h */
|
||||
Generated
+202
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
Generated
+319
@@ -0,0 +1,319 @@
|
||||
[](https://cocoapods.org/pods/Firebase)
|
||||
[](https://cocoapods.org/pods/Firebase)
|
||||
[](https://cocoapods.org/pods/Firebase)
|
||||
|
||||
[![Actions Status][gh-abtesting-badge]][gh-actions]
|
||||
[![Actions Status][gh-appcheck-badge]][gh-actions]
|
||||
[![Actions Status][gh-appdistribution-badge]][gh-actions]
|
||||
[![Actions Status][gh-auth-badge]][gh-actions]
|
||||
[![Actions Status][gh-cocoapods-integration-badge]][gh-actions]
|
||||
[![Actions Status][gh-core-badge]][gh-actions]
|
||||
[![Actions Status][gh-core-diagnostics-badge]][gh-actions]
|
||||
[![Actions Status][gh-crashlytics-badge]][gh-actions]
|
||||
[![Actions Status][gh-database-badge]][gh-actions]
|
||||
[![Actions Status][gh-datatransport-badge]][gh-actions]
|
||||
[![Actions Status][gh-dynamiclinks-badge]][gh-actions]
|
||||
[![Actions Status][gh-firebasepod-badge]][gh-actions]
|
||||
[![Actions Status][gh-firestore-badge]][gh-actions]
|
||||
[![Actions Status][gh-functions-badge]][gh-actions]
|
||||
[![Actions Status][gh-google-utilities-badge]][gh-actions]
|
||||
[![Actions Status][gh-google-utilities-components-badge]][gh-actions]
|
||||
[![Actions Status][gh-inappmessaging-badge]][gh-actions]
|
||||
[![Actions Status][gh-interop-badge]][gh-actions]
|
||||
[![Actions Status][gh-messaging-badge]][gh-actions]
|
||||
[![Actions Status][gh-mlmodeldownloader-badge]][gh-actions]
|
||||
[![Actions Status][gh-performance-badge]][gh-actions]
|
||||
[![Actions Status][gh-remoteconfig-badge]][gh-actions]
|
||||
[![Actions Status][gh-storage-badge]][gh-actions]
|
||||
[![Actions Status][gh-symbolcollision-badge]][gh-actions]
|
||||
[![Actions Status][gh-zip-badge]][gh-actions]
|
||||
|
||||
# Firebase Apple Open Source Development
|
||||
|
||||
This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics
|
||||
and FirebaseML.
|
||||
|
||||
Firebase is an app development platform with tools to help you build, grow and
|
||||
monetize your app. More information about Firebase can be found on the
|
||||
[official Firebase website](https://firebase.google.com).
|
||||
|
||||
## Installation
|
||||
|
||||
See the subsections below for details about the different installation methods.
|
||||
1. [Standard pod install](#standard-pod-install)
|
||||
1. [Swift Package Manager](#swift-package-manager)
|
||||
1. [Installing from the GitHub repo](#installing-from-github)
|
||||
1. [Experimental Carthage](#carthage-ios-only)
|
||||
|
||||
### Standard pod install
|
||||
|
||||
Go to
|
||||
[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup).
|
||||
|
||||
### Swift Package Manager
|
||||
|
||||
Instructions for [Swift Package Manager](https://swift.org/package-manager/) support can be
|
||||
found at [SwiftPackageManager](SwiftPackageManager.md) Markdown file.
|
||||
|
||||
### Installing from GitHub
|
||||
|
||||
These instructions can be used to access the Firebase repo at other branches,
|
||||
tags, or commits.
|
||||
|
||||
#### Background
|
||||
|
||||
See
|
||||
[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod)
|
||||
for instructions and options about overriding pod source locations.
|
||||
|
||||
#### Accessing Firebase Source Snapshots
|
||||
|
||||
All of the official releases are tagged in this repo and available via CocoaPods. To access a local
|
||||
source snapshot or unreleased branch, use Podfile directives like the following:
|
||||
|
||||
To access FirebaseFirestore via a branch:
|
||||
```ruby
|
||||
pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master'
|
||||
pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master'
|
||||
```
|
||||
|
||||
To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do:
|
||||
|
||||
```ruby
|
||||
pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk'
|
||||
pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk'
|
||||
```
|
||||
|
||||
### Carthage (iOS only)
|
||||
|
||||
Instructions for the experimental Carthage distribution are at
|
||||
[Carthage](Carthage.md).
|
||||
|
||||
### Using Firebase from a Framework or a library
|
||||
|
||||
[Using Firebase from a Framework or a library](docs/firebase_in_libraries.md)
|
||||
|
||||
## Development
|
||||
|
||||
To develop Firebase software in this repository, ensure that you have at least
|
||||
the following software:
|
||||
|
||||
* Xcode 12.2 (or later)
|
||||
|
||||
CocoaPods is still the canonical way to develop, but much of the repo now supports
|
||||
development with Swift Package Manager.
|
||||
|
||||
### CocoaPods
|
||||
|
||||
Install
|
||||
* CocoaPods 1.10.0 (or later)
|
||||
* [CocoaPods generate](https://github.com/square/cocoapods-generate)
|
||||
|
||||
For the pod that you want to develop:
|
||||
|
||||
```ruby
|
||||
pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios
|
||||
```
|
||||
|
||||
Note: If the CocoaPods cache is out of date, you may need to run
|
||||
`pod repo update` before the `pod gen` command.
|
||||
|
||||
Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for
|
||||
those platforms. Since 10.2, Xcode does not properly handle multi-platform
|
||||
CocoaPods workspaces.
|
||||
|
||||
Firestore has a self contained Xcode project. See
|
||||
[Firestore/README](Firestore/README.md) Markdown file.
|
||||
|
||||
#### Development for Catalyst
|
||||
* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios`
|
||||
* Check the Mac box in the App-iOS Build Settings
|
||||
* Sign the App in the Settings Signing & Capabilities tab
|
||||
* Click Pods in the Project Manager
|
||||
* Add Signing to the iOS host app and unit test targets
|
||||
* Select the Unit-unit scheme
|
||||
* Run it to build and test
|
||||
|
||||
Alternatively disable signing in each target:
|
||||
* Go to Build Settings tab
|
||||
* Click `+`
|
||||
* Select `Add User-Defined Setting`
|
||||
* Add `CODE_SIGNING_REQUIRED` setting with a value of `NO`
|
||||
|
||||
### Swift Package Manager
|
||||
* To enable test schemes: `./scripts/setup_spm_tests.sh`
|
||||
* `open Package.swift` or double click `Package.swift` in Finder.
|
||||
* Xcode will open the project
|
||||
* Choose a scheme for a library to build or test suite to run
|
||||
* Choose a target platform by selecting the run destination along with the scheme
|
||||
|
||||
### Adding a New Firebase Pod
|
||||
|
||||
See [AddNewPod](AddNewPod.md) Markdown file.
|
||||
|
||||
### Managing Headers and Imports
|
||||
|
||||
See [HeadersImports](HeadersImports.md) Markdown file.
|
||||
|
||||
### Code Formatting
|
||||
|
||||
To ensure that the code is formatted consistently, run the script
|
||||
[./scripts/check.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/check.sh)
|
||||
before creating a PR.
|
||||
|
||||
GitHub Actions will verify that any code changes are done in a style compliant
|
||||
way. Install `clang-format` and `mint`:
|
||||
|
||||
```console
|
||||
brew install clang-format@13
|
||||
brew install mint
|
||||
```
|
||||
|
||||
### Running Unit Tests
|
||||
|
||||
Select a scheme and press Command-u to build a component and run its unit tests.
|
||||
|
||||
### Running Sample Apps
|
||||
In order to run the sample apps and integration tests, you'll need a valid
|
||||
`GoogleService-Info.plist` file. The Firebase Xcode project contains dummy plist
|
||||
files without real values, but can be replaced with real plist files. To get your own
|
||||
`GoogleService-Info.plist` files:
|
||||
|
||||
1. Go to the [Firebase Console](https://console.firebase.google.com/)
|
||||
2. Create a new Firebase project, if you don't already have one
|
||||
3. For each sample app you want to test, create a new Firebase app with the sample app's bundle
|
||||
identifier (e.g. `com.google.Database-Example`)
|
||||
4. Download the resulting `GoogleService-Info.plist` and add it to the Xcode project.
|
||||
|
||||
### Coverage Report Generation
|
||||
|
||||
See [scripts/code_coverage_report/README](scripts/code_coverage_report/README.md) Markdown file.
|
||||
|
||||
## Specific Component Instructions
|
||||
See the sections below for any special instructions for those components.
|
||||
|
||||
### Firebase Auth
|
||||
|
||||
If you're doing specific Firebase Auth development, see
|
||||
[the Auth Sample README](FirebaseAuth/Tests/Sample/README.md) for instructions about
|
||||
building and running the FirebaseAuth pod along with various samples and tests.
|
||||
|
||||
### Firebase Database
|
||||
|
||||
The Firebase Database Integration tests can be run against a locally running Database Emulator
|
||||
or against a production instance.
|
||||
|
||||
To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before
|
||||
running the integration test.
|
||||
|
||||
To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to
|
||||
`FirebaseDatabase/Tests/Resources/GoogleService-Info.plist`. Your Security Rule must be set to
|
||||
[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are
|
||||
running.
|
||||
|
||||
### Firebase Performance Monitoring
|
||||
If you're doing specific Firebase Performance Monitoring development, see
|
||||
[the Performance README](FirebasePerformance/README.md) for instructions about building the SDK
|
||||
and [the Performance TestApp README](FirebasePerformance/Tests/TestApp/README.md) for instructions about
|
||||
integrating Performance with the dev test App.
|
||||
|
||||
### Firebase Storage
|
||||
|
||||
To run the Storage Integration tests, follow the instructions in
|
||||
[FIRStorageIntegrationTests.m](FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m).
|
||||
|
||||
#### Push Notifications
|
||||
|
||||
Push notifications can only be delivered to specially provisioned App IDs in the developer portal.
|
||||
In order to actually test receiving push notifications, you will need to:
|
||||
|
||||
1. Change the bundle identifier of the sample app to something you own in your Apple Developer
|
||||
account, and enable that App ID for push notifications.
|
||||
2. You'll also need to
|
||||
[upload your APNs Provider Authentication Key or certificate to the
|
||||
Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs)
|
||||
at **Project Settings > Cloud Messaging > [Your Firebase App]**.
|
||||
3. Ensure your iOS device is added to your Apple Developer portal as a test device.
|
||||
|
||||
#### iOS Simulator
|
||||
|
||||
The iOS Simulator cannot register for remote notifications, and will not receive push notifications.
|
||||
In order to receive push notifications, you'll have to follow the steps above and run the app on a
|
||||
physical device.
|
||||
|
||||
## Building with Firebase on Apple platforms
|
||||
|
||||
Firebase 8.9.0 introduces official beta support for macOS, Catalyst, and tvOS. watchOS continues
|
||||
to be community supported. Thanks to community contributions for many of the multi-platform PRs.
|
||||
|
||||
At this time, most of Firebase's products are available across Apple platforms. There are still
|
||||
a few gaps, especially on watchOS. For details about the current support matrix, see
|
||||
[this chart](https://firebase.google.com/docs/ios/learn-more#firebase_library_support_by_platform)
|
||||
in Firebase's documentation.
|
||||
|
||||
### watchOS
|
||||
Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and
|
||||
work on watchOS. See the [Independent Watch App Sample](Example/watchOSSample).
|
||||
|
||||
Keep in mind that watchOS is not officially supported by Firebase. While we can catch basic unit
|
||||
test issues with GitHub Actions, there may be some changes where the SDK no longer works as expected
|
||||
on watchOS. If you encounter this, please
|
||||
[file an issue](https://github.com/firebase/firebase-ios-sdk/issues).
|
||||
|
||||
During app setup in the console, you may get to a step that mentions something like "Checking if the
|
||||
app has communicated with our servers". This relies on Analytics and will not work on watchOS.
|
||||
**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected.
|
||||
|
||||
#### Additional Crashlytics Notes
|
||||
* watchOS has limited support. Due to watchOS restrictions, mach exceptions and signal crashes are
|
||||
not recorded. (Crashes in SwiftUI are generated as mach exceptions, so will not be recorded)
|
||||
|
||||
## Combine
|
||||
Thanks to contributions from the community, _FirebaseCombineSwift_ contains support for Apple's Combine
|
||||
framework. This module is currently under development, and not yet supported for use in production
|
||||
environments. Fore more details, please refer to the [docs](FirebaseCombineSwift/README.md).
|
||||
|
||||
## Roadmap
|
||||
|
||||
See [Roadmap](ROADMAP.md) for more about the Firebase Apple SDK Open Source
|
||||
plans and directions.
|
||||
|
||||
## Contributing
|
||||
|
||||
See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase
|
||||
Apple SDK.
|
||||
|
||||
## License
|
||||
|
||||
The contents of this repository are licensed under the
|
||||
[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
|
||||
|
||||
Your use of Firebase is governed by the
|
||||
[Terms of Service for Firebase Services](https://firebase.google.com/terms/).
|
||||
|
||||
[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions
|
||||
[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg
|
||||
[gh-appcheck-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/app_check/badge.svg
|
||||
[gh-appdistribution-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/appdistribution/badge.svg
|
||||
[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg
|
||||
[gh-cocoapods-integration-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/cocoapods-integration/badge.svg
|
||||
[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg
|
||||
[gh-core-diagnostics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core-diagnostics/badge.svg
|
||||
[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg
|
||||
[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg
|
||||
[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg
|
||||
[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg
|
||||
[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg
|
||||
[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg
|
||||
[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg
|
||||
[gh-google-utilities-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/google-utilities/badge.svg
|
||||
[gh-google-utilities-components-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/google-utilities-components/badge.svg
|
||||
[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg
|
||||
[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg
|
||||
[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg
|
||||
[gh-mlmodeldownloader-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/mlmodeldownloader/badge.svg
|
||||
[gh-performance-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/performance/badge.svg
|
||||
[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg
|
||||
[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg
|
||||
[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg
|
||||
[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg
|
||||
Reference in New Issue
Block a user