create
This commit is contained in:
1413
Pods/GTMSessionFetcher/Sources/Core/Public/GTMSessionFetcher/GTMSessionFetcher.h
generated
Normal file
1413
Pods/GTMSessionFetcher/Sources/Core/Public/GTMSessionFetcher/GTMSessionFetcher.h
generated
Normal file
@@ -0,0 +1,1413 @@
|
||||
/* Copyright 2014 Google Inc. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// GTMSessionFetcher is a wrapper around NSURLSession for http operations.
|
||||
//
|
||||
// What does this offer on top of of NSURLSession?
|
||||
//
|
||||
// - Block-style callbacks for useful functionality like progress rather
|
||||
// than delegate methods.
|
||||
// - Out-of-process uploads and downloads using NSURLSession, including
|
||||
// management of fetches after relaunch.
|
||||
// - Integration with GTMAppAuth for invisible management and refresh of
|
||||
// authorization tokens.
|
||||
// - Pretty-printed http logging.
|
||||
// - Cookies handling that does not interfere with or get interfered with
|
||||
// by WebKit cookies or on Mac by Safari and other apps.
|
||||
// - Credentials handling for the http operation.
|
||||
// - Rate-limiting and cookie grouping when fetchers are created with
|
||||
// GTMSessionFetcherService.
|
||||
//
|
||||
// If the bodyData or bodyFileURL property is set, then a POST request is assumed.
|
||||
//
|
||||
// Each fetcher is assumed to be for a one-shot fetch request; don't reuse the object
|
||||
// for a second fetch.
|
||||
//
|
||||
// The fetcher will be self-retained as long as a connection is pending.
|
||||
//
|
||||
// To keep user activity private, URLs must have an https scheme (unless the property
|
||||
// allowedInsecureSchemes is set to permit the scheme.)
|
||||
//
|
||||
// Callbacks will be released when the fetch completes or is stopped, so there is no need
|
||||
// to use weak self references in the callback blocks.
|
||||
//
|
||||
// Sample usage:
|
||||
//
|
||||
// _fetcherService = [[GTMSessionFetcherService alloc] init];
|
||||
//
|
||||
// GTMSessionFetcher *myFetcher = [_fetcherService fetcherWithURLString:myURLString];
|
||||
// myFetcher.retryEnabled = YES;
|
||||
// myFetcher.comment = @"First profile image";
|
||||
//
|
||||
// // Optionally specify a file URL or NSData for the request body to upload.
|
||||
// myFetcher.bodyData = [postString dataUsingEncoding:NSUTF8StringEncoding];
|
||||
//
|
||||
// [myFetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) {
|
||||
// if (error != nil) {
|
||||
// // Server status code or network error.
|
||||
// //
|
||||
// // If the domain is kGTMSessionFetcherStatusDomain then the error code
|
||||
// // is a failure status from the server.
|
||||
// } else {
|
||||
// // Fetch succeeded.
|
||||
// }
|
||||
// }];
|
||||
//
|
||||
// There is also a beginFetch call that takes a pointer and selector for the completion handler;
|
||||
// a pointer and selector is a better style when the callback is a substantial, separate method.
|
||||
//
|
||||
// NOTE: Fetches may retrieve data from the server even though the server
|
||||
// returned an error, so the criteria for success is a non-nil error.
|
||||
// The completion handler is called when the server status is >= 300 with an NSError
|
||||
// having domain kGTMSessionFetcherStatusDomain and code set to the server status.
|
||||
//
|
||||
// Status codes are at <http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html>
|
||||
//
|
||||
//
|
||||
// Background session support:
|
||||
//
|
||||
// Out-of-process uploads and downloads may be created by setting the fetcher's
|
||||
// useBackgroundSession property. Data to be uploaded should be provided via
|
||||
// the uploadFileURL property; the download destination should be specified with
|
||||
// the destinationFileURL. NOTE: Background upload files should be in a location
|
||||
// that will be valid even after the device is restarted, so the file should not
|
||||
// be uploaded from a system temporary or cache directory.
|
||||
//
|
||||
// Background session transfers are slower, and should typically be used only
|
||||
// for very large downloads or uploads (hundreds of megabytes).
|
||||
//
|
||||
// When background sessions are used in iOS apps, the application delegate must
|
||||
// pass through the parameters from UIApplicationDelegate's
|
||||
// application:handleEventsForBackgroundURLSession:completionHandler: to the
|
||||
// fetcher class.
|
||||
//
|
||||
// When the application has been relaunched, it may also create a new fetcher
|
||||
// instance to handle completion of the transfers.
|
||||
//
|
||||
// - (void)application:(UIApplication *)application
|
||||
// handleEventsForBackgroundURLSession:(NSString *)identifier
|
||||
// completionHandler:(void (^)())completionHandler {
|
||||
// // Application was re-launched on completing an out-of-process download.
|
||||
//
|
||||
// // Pass the URLSession info related to this re-launch to the fetcher class.
|
||||
// [GTMSessionFetcher application:application
|
||||
// handleEventsForBackgroundURLSession:identifier
|
||||
// completionHandler:completionHandler];
|
||||
//
|
||||
// // Get a fetcher related to this re-launch and re-hook up a completionHandler to it.
|
||||
// GTMSessionFetcher *fetcher = [GTMSessionFetcher fetcherWithSessionIdentifier:identifier];
|
||||
// NSURL *destinationFileURL = fetcher.destinationFileURL;
|
||||
// fetcher.completionHandler = ^(NSData *data, NSError *error) {
|
||||
// [self downloadCompletedToFile:destinationFileURL error:error];
|
||||
// };
|
||||
// }
|
||||
//
|
||||
//
|
||||
// Threading and queue support:
|
||||
//
|
||||
// Networking always happens on a background thread; there is no advantage to
|
||||
// changing thread or queue to create or start a fetcher.
|
||||
//
|
||||
// Callbacks are run on the main thread; alternatively, the app may set the
|
||||
// fetcher's callbackQueue to a dispatch queue.
|
||||
//
|
||||
// Once the fetcher's beginFetch method has been called, the fetcher's methods and
|
||||
// properties may be accessed from any thread.
|
||||
//
|
||||
// Downloading to disk:
|
||||
//
|
||||
// To have downloaded data saved directly to disk, specify a file URL for the
|
||||
// destinationFileURL property.
|
||||
//
|
||||
// HTTP methods and headers:
|
||||
//
|
||||
// Alternative HTTP methods, like PUT, and custom headers can be specified by
|
||||
// creating the fetcher with an appropriate NSMutableURLRequest.
|
||||
//
|
||||
// Custom headers can also be provided per-request via an instance of `GTMFetcherDecoratorProtocol`
|
||||
// passed to `-[GTMSessionFetcherService addDecorator:]`.
|
||||
//
|
||||
// Caching:
|
||||
//
|
||||
// The fetcher avoids caching. That is best for API requests, but may hurt
|
||||
// repeat fetches of static data. Apps may enable a persistent disk cache by
|
||||
// customizing the config:
|
||||
//
|
||||
// fetcher.configurationBlock = ^(GTMSessionFetcher *configFetcher,
|
||||
// NSURLSessionConfiguration *config) {
|
||||
// config.URLCache = [NSURLCache sharedURLCache];
|
||||
// };
|
||||
//
|
||||
// Or use the standard system config to share cookie storage with web views
|
||||
// and to enable disk caching:
|
||||
//
|
||||
// fetcher.configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
|
||||
//
|
||||
//
|
||||
// Cookies:
|
||||
//
|
||||
// There are three supported mechanisms for remembering cookies between fetches.
|
||||
//
|
||||
// By default, a standalone GTMSessionFetcher uses a mutable array held
|
||||
// statically to track cookies for all instantiated fetchers. This avoids
|
||||
// cookies being set by servers for the application from interfering with
|
||||
// Safari and WebKit cookie settings, and vice versa.
|
||||
// The fetcher cookies are lost when the application quits.
|
||||
//
|
||||
// To rely instead on WebKit's global NSHTTPCookieStorage, set the fetcher's
|
||||
// cookieStorage property:
|
||||
// myFetcher.cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
|
||||
//
|
||||
// To share cookies with other apps, use the method introduced in iOS 9/OS X 10.11:
|
||||
// myFetcher.cookieStorage =
|
||||
// [NSHTTPCookieStorage sharedCookieStorageForGroupContainerIdentifier:kMyCompanyContainedID];
|
||||
//
|
||||
// To ignore existing cookies and only have cookies related to the single fetch
|
||||
// be applied, make a temporary cookie storage object:
|
||||
// myFetcher.cookieStorage = [[GTMSessionCookieStorage alloc] init];
|
||||
//
|
||||
// Note: cookies set while following redirects will be sent to the server, as
|
||||
// the redirects are followed by the fetcher.
|
||||
//
|
||||
// To completely disable cookies, adjust the session configuration appropriately
|
||||
// in the fetcher or fetcher service:
|
||||
// fetcher.configurationBlock = ^(GTMSessionFetcher *configFetcher,
|
||||
// NSURLSessionConfiguration *config) {
|
||||
// config.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever;
|
||||
// config.HTTPShouldSetCookies = NO;
|
||||
// };
|
||||
//
|
||||
// If the fetcher is created from a GTMSessionFetcherService object
|
||||
// then the cookie storage mechanism is set to use the cookie storage in the
|
||||
// service object rather than the static storage. Disabling cookies in the
|
||||
// session configuration set on a service object will disable cookies for all
|
||||
// fetchers created from that GTMSessionFetcherService object, since the session
|
||||
// configuration is propagated to the fetcher.
|
||||
//
|
||||
//
|
||||
// Monitoring data transfers.
|
||||
//
|
||||
// The fetcher supports a variety of properties for progress monitoring
|
||||
// progress with callback blocks.
|
||||
// GTMSessionFetcherSendProgressBlock sendProgressBlock
|
||||
// GTMSessionFetcherReceivedProgressBlock receivedProgressBlock
|
||||
// GTMSessionFetcherDownloadProgressBlock downloadProgressBlock
|
||||
//
|
||||
// If supplied by the server, the anticipated total download size is available
|
||||
// as [[myFetcher response] expectedContentLength] (and may be -1 for unknown
|
||||
// download sizes.)
|
||||
//
|
||||
//
|
||||
// Automatic retrying of fetches
|
||||
//
|
||||
// The fetcher can optionally create a timer and reattempt certain kinds of
|
||||
// fetch failures (status codes 408, request timeout; 502, gateway failure;
|
||||
// 503, service unavailable; 504, gateway timeout; networking errors
|
||||
// NSURLErrorTimedOut and NSURLErrorNetworkConnectionLost.) The user may
|
||||
// set a retry selector to customize the type of errors which will be retried.
|
||||
//
|
||||
// Retries are done in an exponential-backoff fashion (that is, after 1 second,
|
||||
// 2, 4, 8, and so on.)
|
||||
//
|
||||
// Enabling automatic retries looks like this:
|
||||
// myFetcher.retryEnabled = YES;
|
||||
//
|
||||
// With retries enabled, the completion callbacks are called only
|
||||
// when no more retries will be attempted. Calling the fetcher's stopFetching
|
||||
// method will terminate the retry timer, without the finished or failure
|
||||
// selectors being invoked.
|
||||
//
|
||||
// Optionally, the client may set the maximum retry interval:
|
||||
// myFetcher.maxRetryInterval = 60.0; // in seconds; default is 60 seconds
|
||||
// // for downloads, 600 for uploads
|
||||
//
|
||||
// Servers should never send a 400 or 500 status for errors that are retryable
|
||||
// by clients, as those values indicate permanent failures. In nearly all
|
||||
// cases, the default standard retry behavior is correct for clients, and no
|
||||
// custom client retry behavior is needed or appropriate. Servers that send
|
||||
// non-retryable status codes and expect the client to retry the request are
|
||||
// faulty.
|
||||
//
|
||||
// Still, the client may provide a block to determine if a status code or other
|
||||
// error should be retried. The block returns YES to set the retry timer or NO
|
||||
// to fail without additional fetch attempts.
|
||||
//
|
||||
// The retry method may return the |suggestedWillRetry| argument to get the
|
||||
// default retry behavior. Server status codes are present in the
|
||||
// error argument, and have the domain kGTMSessionFetcherStatusDomain. The
|
||||
// user's method may look something like this:
|
||||
//
|
||||
// myFetcher.retryBlock = ^(BOOL suggestedWillRetry, NSError *error,
|
||||
// GTMSessionFetcherRetryResponse response) {
|
||||
// // Perhaps examine error.domain and error.code, or fetcher.retryCount
|
||||
// //
|
||||
// // Respond with YES to start the retry timer, NO to proceed to the failure
|
||||
// // callback, or suggestedWillRetry to get default behavior for the
|
||||
// // current error domain and code values.
|
||||
// response(suggestedWillRetry);
|
||||
// };
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#import <UIKit/UIKit.h>
|
||||
#endif
|
||||
#if TARGET_OS_WATCH
|
||||
#import <WatchKit/WatchKit.h>
|
||||
#endif
|
||||
|
||||
// By default it is stripped from non DEBUG builds. Developers can override
|
||||
// this in their project settings.
|
||||
#ifndef STRIP_GTM_FETCH_LOGGING
|
||||
#if !DEBUG
|
||||
#define STRIP_GTM_FETCH_LOGGING 1
|
||||
#else
|
||||
#define STRIP_GTM_FETCH_LOGGING 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Logs in debug builds.
|
||||
#ifndef GTMSESSION_LOG_DEBUG
|
||||
#if DEBUG
|
||||
#define GTMSESSION_LOG_DEBUG(...) NSLog(__VA_ARGS__)
|
||||
#else
|
||||
#define GTMSESSION_LOG_DEBUG(...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Asserts in debug builds (or logs in debug builds if GTMSESSION_ASSERT_AS_LOG
|
||||
// or NS_BLOCK_ASSERTIONS are defined.)
|
||||
#ifndef GTMSESSION_ASSERT_DEBUG
|
||||
#if DEBUG && !defined(NS_BLOCK_ASSERTIONS) && !GTMSESSION_ASSERT_AS_LOG
|
||||
#undef GTMSESSION_ASSERT_AS_LOG
|
||||
#define GTMSESSION_ASSERT_AS_LOG 1
|
||||
#endif
|
||||
|
||||
#if DEBUG && !GTMSESSION_ASSERT_AS_LOG
|
||||
#define GTMSESSION_ASSERT_DEBUG(...) NSAssert(__VA_ARGS__)
|
||||
#elif DEBUG
|
||||
#define GTMSESSION_ASSERT_DEBUG(pred, ...) \
|
||||
if (!(pred)) { \
|
||||
NSLog(__VA_ARGS__); \
|
||||
}
|
||||
#else
|
||||
#define GTMSESSION_ASSERT_DEBUG(pred, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Asserts in debug builds, logs in release builds (or logs in debug builds if
|
||||
// GTMSESSION_ASSERT_AS_LOG is defined.)
|
||||
#ifndef GTMSESSION_ASSERT_DEBUG_OR_LOG
|
||||
#if DEBUG && !GTMSESSION_ASSERT_AS_LOG
|
||||
#define GTMSESSION_ASSERT_DEBUG_OR_LOG(...) NSAssert(__VA_ARGS__)
|
||||
#else
|
||||
#define GTMSESSION_ASSERT_DEBUG_OR_LOG(pred, ...) \
|
||||
if (!(pred)) { \
|
||||
NSLog(__VA_ARGS__); \
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Macro useful for more verbose logging from NSURLSession during debugging.
|
||||
#if 0
|
||||
#define GTMSESSION_LOG_DEBUG_VERBOSE(...) GTMSESSION_LOG_DEBUG(__VA_ARGS__)
|
||||
#else
|
||||
#define GTMSESSION_LOG_DEBUG_VERBOSE(...)
|
||||
#endif
|
||||
|
||||
// For iOS, the fetcher can declare itself a background task to allow fetches
|
||||
// to finish when the app leaves the foreground.
|
||||
//
|
||||
// (This is unrelated to providing a background configuration, which allows
|
||||
// out-of-process uploads and downloads.)
|
||||
//
|
||||
// To disallow use of background tasks during fetches, the target should define
|
||||
// GTM_BACKGROUND_TASK_FETCHING to 0, or alternatively may set the
|
||||
// skipBackgroundTask property to YES.
|
||||
#if !defined(GTM_BACKGROUND_TASK_FETCHING) && \
|
||||
(TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_MACCATALYST)
|
||||
#define GTM_BACKGROUND_TASK_FETCHING 1
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// When creating background sessions to perform out-of-process uploads and
|
||||
// downloads, on app launch any background sessions must be reconnected in
|
||||
// order to receive events that occurred while the app was not running.
|
||||
//
|
||||
// The fetcher will automatically attempt to recreate the sessions on app
|
||||
// start, but doing so reads from NSUserDefaults. This may have launch-time
|
||||
// performance impacts.
|
||||
//
|
||||
// To avoid launch performance impacts, on iPhone/iPad with iOS 13+ the
|
||||
// GTMSessionFetcher class will register for the app launch notification and
|
||||
// perform the reconnect then.
|
||||
//
|
||||
// Apps targeting Mac or older iOS SDKs can opt into the new behavior by defining
|
||||
// GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH=1.
|
||||
//
|
||||
// Apps targeting new SDKs can force the old behavior by defining
|
||||
// GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH = 0.
|
||||
#ifndef GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH
|
||||
// Default to the on-launch behavior for iOS 13+.
|
||||
#if TARGET_OS_IOS && defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
|
||||
#define GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH 1
|
||||
#else
|
||||
#define GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// Notifications
|
||||
//
|
||||
// Fetch started and stopped, and fetch retry delay started and stopped.
|
||||
extern NSString *const kGTMSessionFetcherStartedNotification;
|
||||
extern NSString *const kGTMSessionFetcherStoppedNotification;
|
||||
extern NSString *const kGTMSessionFetcherRetryDelayStartedNotification;
|
||||
extern NSString *const kGTMSessionFetcherRetryDelayStoppedNotification;
|
||||
|
||||
// Completion handler notification. This is intended for use by code capturing
|
||||
// and replaying fetch requests and results for testing. For fetches where
|
||||
// destinationFileURL or accumulateDataBlock is set for the fetcher, the data
|
||||
// will be nil for successful fetches.
|
||||
//
|
||||
// This notification is posted on the main thread.
|
||||
extern NSString *const kGTMSessionFetcherCompletionInvokedNotification;
|
||||
extern NSString *const kGTMSessionFetcherCompletionDataKey;
|
||||
extern NSString *const kGTMSessionFetcherCompletionErrorKey;
|
||||
|
||||
// Constants for NSErrors created by the fetcher (excluding server status errors,
|
||||
// and error objects originating in the OS.)
|
||||
extern NSString *const kGTMSessionFetcherErrorDomain;
|
||||
|
||||
// The fetcher turns server error status values (3XX, 4XX, 5XX) into NSErrors
|
||||
// with domain kGTMSessionFetcherStatusDomain.
|
||||
//
|
||||
// Any server response body data accompanying the status error is added to the
|
||||
// userInfo dictionary with key kGTMSessionFetcherStatusDataKey.
|
||||
extern NSString *const kGTMSessionFetcherStatusDomain;
|
||||
extern NSString *const kGTMSessionFetcherStatusDataKey;
|
||||
extern NSString *const kGTMSessionFetcherStatusDataContentTypeKey;
|
||||
|
||||
// When a fetch fails with an error, these keys are included in the error userInfo
|
||||
// dictionary if retries were attempted.
|
||||
extern NSString *const kGTMSessionFetcherNumberOfRetriesDoneKey;
|
||||
extern NSString *const kGTMSessionFetcherElapsedIntervalWithRetriesKey;
|
||||
|
||||
// Background session support requires access to NSUserDefaults.
|
||||
// If [NSUserDefaults standardUserDefaults] doesn't yield the correct NSUserDefaults for your usage,
|
||||
// ie for an App Extension, then implement this class/method to return the correct NSUserDefaults.
|
||||
// https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW6
|
||||
@interface GTMSessionFetcherUserDefaultsFactory : NSObject
|
||||
|
||||
+ (NSUserDefaults *)fetcherUserDefaults;
|
||||
|
||||
@end
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef NS_ENUM(NSInteger, GTMSessionFetcherError) {
|
||||
GTMSessionFetcherErrorDownloadFailed = -1,
|
||||
GTMSessionFetcherErrorUploadChunkUnavailable = -2,
|
||||
GTMSessionFetcherErrorBackgroundExpiration = -3,
|
||||
GTMSessionFetcherErrorBackgroundFetchFailed = -4,
|
||||
GTMSessionFetcherErrorInsecureRequest = -5,
|
||||
GTMSessionFetcherErrorTaskCreationFailed = -6,
|
||||
|
||||
// This error is only used if `stopFetchingTriggersCompletionHandler` is
|
||||
// enabled and `-stopFetching` is called on that fetcher.
|
||||
GTMSessionFetcherErrorUserCancelled = -7,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, GTMSessionFetcherStatus) {
|
||||
// Standard http status codes.
|
||||
GTMSessionFetcherStatusNotModified = 304,
|
||||
GTMSessionFetcherStatusBadRequest = 400,
|
||||
GTMSessionFetcherStatusUnauthorized = 401,
|
||||
GTMSessionFetcherStatusForbidden = 403,
|
||||
GTMSessionFetcherStatusPreconditionFailed = 412
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@class GTMSessionCookieStorage;
|
||||
@class GTMSessionFetcher;
|
||||
@class GTMSessionFetcherService;
|
||||
|
||||
// The configuration block is for modifying the NSURLSessionConfiguration only.
|
||||
// DO NOT change any fetcher properties in the configuration block.
|
||||
typedef void (^GTMSessionFetcherConfigurationBlock)(GTMSessionFetcher *fetcher,
|
||||
NSURLSessionConfiguration *configuration);
|
||||
typedef void (^GTMSessionFetcherSystemCompletionHandler)(void);
|
||||
typedef void (^GTMSessionFetcherCompletionHandler)(NSData *_Nullable data,
|
||||
NSError *_Nullable error);
|
||||
typedef NSURLSession *_Nullable (^GTMSessionFetcherSessionCreationBlock)(
|
||||
id<NSURLSessionDelegate> _Nullable sessionDelegate);
|
||||
typedef void (^GTMSessionFetcherBodyStreamProviderResponse)(NSInputStream *bodyStream);
|
||||
typedef void (^GTMSessionFetcherBodyStreamProvider)(
|
||||
GTMSessionFetcherBodyStreamProviderResponse response);
|
||||
typedef void (^GTMSessionFetcherDidReceiveResponseDispositionBlock)(
|
||||
NSURLSessionResponseDisposition disposition);
|
||||
typedef void (^GTMSessionFetcherDidReceiveResponseBlock)(
|
||||
NSURLResponse *response, GTMSessionFetcherDidReceiveResponseDispositionBlock dispositionBlock);
|
||||
typedef void (^GTMSessionFetcherChallengeDispositionBlock)(
|
||||
NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *_Nullable credential);
|
||||
typedef void (^GTMSessionFetcherChallengeBlock)(
|
||||
GTMSessionFetcher *fetcher, NSURLAuthenticationChallenge *challenge,
|
||||
GTMSessionFetcherChallengeDispositionBlock dispositionBlock);
|
||||
typedef void (^GTMSessionFetcherWillRedirectResponse)(NSURLRequest *_Nullable redirectedRequest);
|
||||
typedef void (^GTMSessionFetcherWillRedirectBlock)(NSHTTPURLResponse *redirectResponse,
|
||||
NSURLRequest *redirectRequest,
|
||||
GTMSessionFetcherWillRedirectResponse response);
|
||||
typedef void (^GTMSessionFetcherAccumulateDataBlock)(NSData *_Nullable buffer);
|
||||
typedef void (^GTMSessionFetcherSimulateByteTransferBlock)(NSData *_Nullable buffer,
|
||||
int64_t bytesWritten,
|
||||
int64_t totalBytesWritten,
|
||||
int64_t totalBytesExpectedToWrite);
|
||||
typedef void (^GTMSessionFetcherReceivedProgressBlock)(int64_t bytesWritten,
|
||||
int64_t totalBytesWritten);
|
||||
typedef void (^GTMSessionFetcherDownloadProgressBlock)(int64_t bytesWritten,
|
||||
int64_t totalBytesWritten,
|
||||
int64_t totalBytesExpectedToWrite);
|
||||
typedef void (^GTMSessionFetcherSendProgressBlock)(int64_t bytesSent, int64_t totalBytesSent,
|
||||
int64_t totalBytesExpectedToSend);
|
||||
typedef void (^GTMSessionFetcherWillCacheURLResponseResponse)(
|
||||
NSCachedURLResponse *_Nullable cachedResponse);
|
||||
typedef void (^GTMSessionFetcherWillCacheURLResponseBlock)(
|
||||
NSCachedURLResponse *proposedResponse,
|
||||
GTMSessionFetcherWillCacheURLResponseResponse responseBlock);
|
||||
typedef void (^GTMSessionFetcherRetryResponse)(BOOL shouldRetry);
|
||||
typedef void (^GTMSessionFetcherRetryBlock)(BOOL suggestedWillRetry, NSError *_Nullable error,
|
||||
GTMSessionFetcherRetryResponse response);
|
||||
|
||||
API_AVAILABLE(ios(10.0), macosx(10.12), tvos(10.0), watchos(6.0))
|
||||
typedef void (^GTMSessionFetcherMetricsCollectionBlock)(NSURLSessionTaskMetrics *metrics);
|
||||
|
||||
typedef void (^GTMSessionFetcherTestResponse)(NSHTTPURLResponse *_Nullable response,
|
||||
NSData *_Nullable data, NSError *_Nullable error);
|
||||
typedef void (^GTMSessionFetcherTestBlock)(GTMSessionFetcher *fetcherToTest,
|
||||
GTMSessionFetcherTestResponse testResponse);
|
||||
|
||||
// Provides access to a user-agent string calculated on demand.
|
||||
//
|
||||
// Methods and properties on this protocol must be thread-safe. In addition,
|
||||
// |userAgentCache| must not block the calling thread to perform I/O.
|
||||
@protocol GTMUserAgentProvider <NSObject>
|
||||
|
||||
// Non-nil user-agent string if |userAgent| has already been cached and is safe
|
||||
// to read without blocking the calling thread, |nil| otherwise.
|
||||
@property(atomic, readonly, nullable, copy) NSString *cachedUserAgent;
|
||||
|
||||
// The user-agent string, calculated on demand. This might block the calling thread if
|
||||
// |userAgentCached| is NO.
|
||||
@property(atomic, readonly, copy) NSString *userAgent;
|
||||
|
||||
@end
|
||||
|
||||
/// Provides a User-Agent string that is known at the time the fetcher is created.
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface GTMUserAgentStringProvider : NSObject<GTMUserAgentProvider>
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (instancetype)initWithUserAgentString:(NSString *)userAgentString NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
||||
// Calculates the User-Agent string on demand using |GTMFetcherStandardUserAgentString()| given an
|
||||
// optional bundle.
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface GTMStandardUserAgentProvider : NSObject<GTMUserAgentProvider>
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (instancetype)initWithBundle:(nullable NSBundle *)bundle NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
||||
void GTMSessionFetcherAssertValidSelector(id _Nullable obj, SEL _Nullable sel, ...);
|
||||
|
||||
// Utility functions for applications self-identifying to servers via a
|
||||
// user-agent header
|
||||
|
||||
// The "standard" user agent includes the application identifier, taken from the bundle,
|
||||
// followed by a space and the system version string. Pass nil to use +mainBundle as the source
|
||||
// of the bundle identifier.
|
||||
//
|
||||
// Applications may use this as a starting point for their own user agent strings, perhaps
|
||||
// with additional sections appended. Use GTMFetcherCleanedUserAgentString() below to
|
||||
// clean up any string being added to the user agent.
|
||||
NSString *GTMFetcherStandardUserAgentString(NSBundle *_Nullable bundle);
|
||||
|
||||
// Make a generic name and version for the current application, like
|
||||
// com.example.MyApp/1.2.3 relying on the bundle identifier and the
|
||||
// CFBundleShortVersionString or CFBundleVersion.
|
||||
//
|
||||
// The bundle ID may be overridden as the base identifier string by
|
||||
// adding to the bundle's Info.plist a "GTMUserAgentID" key.
|
||||
//
|
||||
// The application version may be overridden by adding to the bundle's
|
||||
// Info.plist a "GTMUserAgentVersion" key.
|
||||
//
|
||||
// If no bundle ID or override is available, the process name preceded
|
||||
// by "proc_" is used.
|
||||
NSString *GTMFetcherApplicationIdentifier(NSBundle *_Nullable bundle);
|
||||
|
||||
// Make an identifier like "MacOSX/10.7.1" or "iPod_Touch/4.1 hw/iPod1_1"
|
||||
NSString *GTMFetcherSystemVersionString(void);
|
||||
|
||||
// Make a parseable user-agent identifier from the given string, replacing whitespace
|
||||
// and commas with underscores, and removing other characters that may interfere
|
||||
// with parsing of the full user-agent string.
|
||||
//
|
||||
// For example, @"[My App]" would become @"My_App"
|
||||
NSString *GTMFetcherCleanedUserAgentString(NSString *str);
|
||||
|
||||
// Grab the data from an input stream. Since streams cannot be assumed to be rewindable,
|
||||
// this may be destructive; the caller can try to rewind the stream (by setting the
|
||||
// NSStreamFileCurrentOffsetKey property) or can just use the NSData to make a new
|
||||
// NSInputStream. This function is intended to facilitate testing rather than be used in
|
||||
// production.
|
||||
//
|
||||
// This function operates synchronously on the current thread. Depending on how the
|
||||
// input stream is implemented, it may be appropriate to dispatch to a different
|
||||
// queue before calling this function.
|
||||
//
|
||||
// Failure is indicated by a returned data value of nil.
|
||||
NSData *_Nullable GTMDataFromInputStream(NSInputStream *inputStream, NSError **outError);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
// Completion handler passed to -[GTMFetcherDecoratorProtocol fetcherWillStart:completionHandler:].
|
||||
typedef void (^GTMFetcherDecoratorFetcherWillStartCompletionHandler)(NSURLRequest *_Nullable,
|
||||
NSError *_Nullable);
|
||||
|
||||
// Allows intercepting a request and optionally modifying it before the request (or a retry)
|
||||
// is sent. See `-[GTMSessionFetcherService addDecorator:]` and `-[GTMSessionFetcherService
|
||||
// removeDecorator:]`.
|
||||
//
|
||||
// Decorator methods must be thread-safe, as they might be invoked on any queue.
|
||||
@protocol GTMFetcherDecoratorProtocol <NSObject>
|
||||
|
||||
// Invoked just before a fetcher's request starts.
|
||||
//
|
||||
// After the decorator's work is complete, the decorator must invoke `handler(request, error)`
|
||||
// either synchronously or asynchronously (on any queue).
|
||||
//
|
||||
// If no changes are to be made, pass `nil` for both `request` and `error`.
|
||||
//
|
||||
// Otherwise, if `error` is non-nil, then the fetcher is stopped with the given error, and any
|
||||
// further decorators' `-fetcherWillStart:completionHandler:` methods are not invoked.
|
||||
//
|
||||
// Otherwise, the decorator may use `[fetcher.request mutableCopy]`, make changes to the mutable
|
||||
// copy of the request, and pass the result to the handler via the `request` parameter.
|
||||
//
|
||||
// To distinguish the initial fetch from retries, the decorator can look at `fetcher.retryCount`.
|
||||
//
|
||||
// This method must not block the caller (e.g., performing synchronous I/O). Perform any blocking
|
||||
// work or I/O on a different queue, then invoke `handler` with the results after the blocking work
|
||||
// completes.
|
||||
- (void)fetcherWillStart:(GTMSessionFetcher *)fetcher
|
||||
completionHandler:(GTMFetcherDecoratorFetcherWillStartCompletionHandler)handler;
|
||||
|
||||
// Invoked just after a fetcher's request finishes (either on success or on failure).
|
||||
//
|
||||
// After the decorator's work is complete, the decorator must invoke `handler()` either
|
||||
// synchronously or asynchronously (on any queue).
|
||||
//
|
||||
// To access the result of the fetch, the decorator can look at `fetcher.response`.
|
||||
//
|
||||
// This method must not block the caller (e.g., performing synchronous I/O). Perform any blocking
|
||||
// work or I/O on a different queue, then invoke `handler` with the results after the blocking work
|
||||
// completes.
|
||||
- (void)fetcherDidFinish:(GTMSessionFetcher *)fetcher
|
||||
withData:(nullable NSData *)data
|
||||
error:(nullable NSError *)error
|
||||
completionHandler:(void (^)(void))handler;
|
||||
|
||||
@end
|
||||
|
||||
// This protocol allows abstract references to the fetcher service.
|
||||
//
|
||||
// Apps should not need to use this protocol.
|
||||
@protocol GTMSessionFetcherServiceProtocol <NSObject>
|
||||
|
||||
- (GTMSessionFetcher *)fetcherWithRequest:(NSURLRequest *)request;
|
||||
|
||||
@property(atomic, strong, null_resettable, readonly) dispatch_queue_t callbackQueue;
|
||||
|
||||
// These properties are being removed from the protocol; clients should not attempt new
|
||||
// accesses to them.
|
||||
@property(atomic, assign) BOOL reuseSession;
|
||||
@property(atomic, readonly, strong, nullable) NSOperationQueue *delegateQueue;
|
||||
|
||||
@end // @protocol GTMSessionFetcherServiceProtocol
|
||||
|
||||
__deprecated_msg("implement GTMSessionFetcherAuthorizer instead")
|
||||
@protocol GTMFetcherAuthorizationProtocol<NSObject>
|
||||
@required
|
||||
// This protocol allows us to call the authorizer without requiring its sources
|
||||
// in this project. This protocol is deprecated in favor of GTMSessionFetcherAuthorizer,
|
||||
// and implementations should move to that protocol in anticipation of
|
||||
// GTMFetcherAuthorizationProtocol being deleted in a future release.
|
||||
|
||||
// This method is being phased out. While implementing it is necessary to satisfy
|
||||
// the protocol's @required restrictions, conforming implementations that implement
|
||||
// authorizeRequest:completionHandler: will have that called instead.
|
||||
// be removed in a future version when GTMFetcherAuthorizationProtocol is
|
||||
// also removed.
|
||||
- (void)authorizeRequest:(nullable NSMutableURLRequest *)request
|
||||
delegate:(id)delegate
|
||||
didFinishSelector:(SEL)sel
|
||||
__deprecated_msg("implement authorizeRequest:completionHandler: instead");
|
||||
|
||||
- (void)stopAuthorization;
|
||||
|
||||
- (void)stopAuthorizationForRequest:(NSURLRequest *)request;
|
||||
|
||||
- (BOOL)isAuthorizingRequest:(NSURLRequest *)request;
|
||||
|
||||
- (BOOL)isAuthorizedRequest:(NSURLRequest *)request;
|
||||
|
||||
@property(atomic, strong, readonly, nullable) NSString *userEmail;
|
||||
|
||||
@optional
|
||||
|
||||
// This method is prefered over authorizeRequest:delegate:didFinishSelector:, and
|
||||
// becomes a required method in the GTMSessionFetcherAuthorizer protocol.
|
||||
- (void)authorizeRequest:(nullable NSMutableURLRequest *)request
|
||||
completionHandler:(void (^)(NSError *_Nullable error))handler;
|
||||
|
||||
// Indicate if authorization may be attempted. Even if this succeeds,
|
||||
// authorization may fail if the user's permissions have been revoked.
|
||||
@property(atomic, readonly) BOOL canAuthorize;
|
||||
|
||||
// For development only, allow authorization of non-SSL requests, allowing
|
||||
// transmission of the bearer token unencrypted.
|
||||
@property(atomic, assign) BOOL shouldAuthorizeAllRequests;
|
||||
|
||||
@property(atomic, weak, nullable) id<GTMSessionFetcherServiceProtocol> fetcherService;
|
||||
|
||||
- (BOOL)primeForRefresh;
|
||||
|
||||
@end
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
||||
// This is the preferred, forward-going protocol for fetcher authorization. it
|
||||
// currently implements the deprecated GTMFetcherAuthorizationProtocol in order
|
||||
// to avoid changing the GTMSessionFetcher API surface while implementations
|
||||
// migrate. In a future release, the non-deprecated method declarations will be
|
||||
// moved here and the GTMFetcherAuthorizationProtocol and the deprecated methods
|
||||
// deleted.
|
||||
@protocol GTMSessionFetcherAuthorizer <GTMFetcherAuthorizationProtocol>
|
||||
// This protocol allows us to call the authorizer without requiring its sources
|
||||
// in this project.
|
||||
#pragma clang diagnostic pop
|
||||
@required
|
||||
|
||||
// Authorizers should implement this method rather than the selector-based
|
||||
// callback form from the old protocol.
|
||||
- (void)authorizeRequest:(nullable NSMutableURLRequest *)request
|
||||
completionHandler:(void (^)(NSError *_Nullable error))handler;
|
||||
|
||||
@optional
|
||||
// This method is re-declared here as @optional only to quash deprecation warnings
|
||||
// on the @required declaration from GTMFetcherAuthorizationProtocol, which
|
||||
// must still be provided by conforming implementations. Once the old protocol has
|
||||
// been removed, this method will be marked unavailable to trigger implementations
|
||||
// to stop providing it, and it will eventually be removed.
|
||||
- (void)authorizeRequest:(nullable NSMutableURLRequest *)request
|
||||
delegate:(id)delegate
|
||||
didFinishSelector:(SEL)sel;
|
||||
|
||||
@end
|
||||
|
||||
#if GTM_BACKGROUND_TASK_FETCHING
|
||||
// A protocol for an alternative target for messages from GTMSessionFetcher to UIApplication.
|
||||
// Set the target using +[GTMSessionFetcher setSubstituteUIApplication:]
|
||||
@protocol GTMUIApplicationProtocol <NSObject>
|
||||
- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithName:(nullable NSString *)taskName
|
||||
expirationHandler:(void (^__nullable)(void))handler;
|
||||
- (void)endBackgroundTask:(UIBackgroundTaskIdentifier)identifier;
|
||||
@end
|
||||
#endif
|
||||
|
||||
#pragma mark -
|
||||
|
||||
// GTMSessionFetcher objects are used for async retrieval of an http get or post
|
||||
//
|
||||
// See additional comments at the beginning of this file
|
||||
@interface GTMSessionFetcher : NSObject <NSURLSessionDelegate>
|
||||
|
||||
// Create a fetcher
|
||||
//
|
||||
// fetcherWithRequest will return an autoreleased fetcher, but if
|
||||
// the connection is successfully created, the connection should retain the
|
||||
// fetcher for the life of the connection as well. So the caller doesn't have
|
||||
// to retain the fetcher explicitly unless they want to be able to cancel it.
|
||||
+ (instancetype)fetcherWithRequest:(nullable NSURLRequest *)request;
|
||||
|
||||
// Convenience methods that make a request, like +fetcherWithRequest
|
||||
+ (instancetype)fetcherWithURL:(NSURL *)requestURL;
|
||||
+ (instancetype)fetcherWithURLString:(NSString *)requestURLString;
|
||||
|
||||
// Methods for creating fetchers to continue previous fetches.
|
||||
+ (instancetype)fetcherWithDownloadResumeData:(NSData *)resumeData;
|
||||
+ (nullable instancetype)fetcherWithSessionIdentifier:(NSString *)sessionIdentifier;
|
||||
|
||||
// Returns an array of currently active fetchers for background sessions,
|
||||
// both restarted and newly created ones.
|
||||
+ (NSArray<GTMSessionFetcher *> *)fetchersForBackgroundSessions;
|
||||
|
||||
// Designated initializer.
|
||||
//
|
||||
// Applications should create fetchers with a "fetcherWith..." method on a fetcher
|
||||
// service or a class method, not with this initializer.
|
||||
//
|
||||
// The configuration should typically be nil. Applications needing to customize
|
||||
// the configuration may do so by setting the configurationBlock property.
|
||||
- (instancetype)initWithRequest:(nullable NSURLRequest *)request
|
||||
configuration:(nullable NSURLSessionConfiguration *)configuration;
|
||||
|
||||
// The fetcher's request. This may not be set after beginFetch has been invoked. The request
|
||||
// may change due to redirects.
|
||||
@property(atomic, strong, nullable) NSURLRequest *request;
|
||||
|
||||
// Set a header field value on the request. Header field value changes will not
|
||||
// affect a fetch after the fetch has begun.
|
||||
- (void)setRequestValue:(nullable NSString *)value forHTTPHeaderField:(NSString *)field;
|
||||
|
||||
// Data used for resuming a download task.
|
||||
@property(atomic, readonly, nullable) NSData *downloadResumeData;
|
||||
|
||||
// The configuration; this must be set before the fetch begins. If no configuration is
|
||||
// set or inherited from the fetcher service, then the fetcher uses an ephemeral config.
|
||||
//
|
||||
// NOTE: This property should typically be nil. Applications needing to customize
|
||||
// the configuration should do so by setting the configurationBlock property.
|
||||
// That allows the fetcher to pick an appropriate base configuration, with the
|
||||
// application setting only the configuration properties it needs to customize.
|
||||
@property(atomic, strong, nullable) NSURLSessionConfiguration *configuration;
|
||||
|
||||
// A block the client may use to customize the configuration used to create the session.
|
||||
//
|
||||
// This is called synchronously, either on the thread that begins the fetch or, during a retry,
|
||||
// on the main thread. The configuration block may be called repeatedly if multiple fetchers are
|
||||
// created.
|
||||
//
|
||||
// The configuration block is for modifying the NSURLSessionConfiguration only.
|
||||
// DO NOT change any fetcher properties in the configuration block. Fetcher properties
|
||||
// may be set in the fetcher service prior to fetcher creation, or on the fetcher prior
|
||||
// to invoking beginFetch.
|
||||
@property(atomic, copy, nullable) GTMSessionFetcherConfigurationBlock configurationBlock;
|
||||
|
||||
// A session is created as needed by the fetcher. A fetcher service object
|
||||
// may maintain sessions for multiple fetches to the same host.
|
||||
@property(atomic, strong, nullable) NSURLSession *session;
|
||||
|
||||
// The task in flight.
|
||||
@property(atomic, readonly, nullable) NSURLSessionTask *sessionTask;
|
||||
|
||||
// The background session identifier.
|
||||
@property(atomic, readonly, nullable) NSString *sessionIdentifier;
|
||||
|
||||
// Indicates a fetcher created to finish a background session task.
|
||||
@property(atomic, readonly) BOOL wasCreatedFromBackgroundSession;
|
||||
|
||||
// Indicates the client has committed to reconnecting this background session when
|
||||
// the app restarts. If this value is YES, the session fetcher will not automatically
|
||||
// call beginFetchWithCompletionHandler: on the restored fetcher on app start, and
|
||||
// the session will not handle system events until the client explicitly does.
|
||||
@property(atomic, assign) BOOL clientWillReconnectBackgroundSession;
|
||||
|
||||
// Additional user-supplied data to encode into the session identifier. Since session identifier
|
||||
// length limits are unspecified, this should be kept small. Key names beginning with an underscore
|
||||
// are reserved for use by the fetcher.
|
||||
@property(atomic, strong, nullable) NSDictionary<NSString *, NSString *> *sessionUserInfo;
|
||||
|
||||
// The human-readable description to be assigned to the task.
|
||||
@property(atomic, copy, nullable) NSString *taskDescription;
|
||||
|
||||
// The priority assigned to the task, if any. Use NSURLSessionTaskPriorityLow,
|
||||
// NSURLSessionTaskPriorityDefault, or NSURLSessionTaskPriorityHigh.
|
||||
@property(atomic, assign) float taskPriority;
|
||||
|
||||
// An optional provider to calculate the User-Agent string on demand. If non-nil and
|
||||
// an HTTP header field for User-Agent is not set, this is queried before sending out
|
||||
// the network request for the User-Agent string.
|
||||
@property(atomic, strong, nullable) id<GTMUserAgentProvider> userAgentProvider;
|
||||
|
||||
// The fetcher encodes information used to resume a session in the session identifier.
|
||||
// This method, intended for internal use returns the encoded information. The sessionUserInfo
|
||||
// dictionary is stored as identifier metadata.
|
||||
- (nullable NSDictionary<NSString *, NSString *> *)sessionIdentifierMetadata;
|
||||
|
||||
#if TARGET_OS_IPHONE && !TARGET_OS_WATCH
|
||||
// The app should pass to this method the completion handler passed in the app delegate method
|
||||
// application:handleEventsForBackgroundURLSession:completionHandler:
|
||||
+ (void)application:(UIApplication *)application
|
||||
handleEventsForBackgroundURLSession:(NSString *)identifier
|
||||
completionHandler:(GTMSessionFetcherSystemCompletionHandler)completionHandler;
|
||||
#endif
|
||||
|
||||
// Indicate that a newly created session should be a background session.
|
||||
// A new session identifier will be created by the fetcher.
|
||||
//
|
||||
// Warning: The only thing background sessions are for is rare download
|
||||
// of huge, batched files of data. And even just for those, there's a lot
|
||||
// of pain and hackery needed to get transfers to actually happen reliably
|
||||
// with background sessions.
|
||||
//
|
||||
// Don't try to upload or download in many background sessions, since the system
|
||||
// will impose an exponentially increasing time penalty to prevent the app from
|
||||
// getting too much background execution time.
|
||||
//
|
||||
// References:
|
||||
//
|
||||
// "Moving to Fewer, Larger Transfers"
|
||||
// https://forums.developer.apple.com/thread/14853
|
||||
//
|
||||
// "NSURLSession’s Resume Rate Limiter"
|
||||
// https://forums.developer.apple.com/thread/14854
|
||||
//
|
||||
// "Background Session Task state persistence"
|
||||
// https://forums.developer.apple.com/thread/11554
|
||||
//
|
||||
@property(atomic, assign) BOOL useBackgroundSession;
|
||||
|
||||
// Indicates if the fetcher was started using a background session.
|
||||
@property(atomic, readonly, getter=isUsingBackgroundSession) BOOL usingBackgroundSession;
|
||||
|
||||
// Indicates if uploads should use an upload task. This is always set for file or stream-provider
|
||||
// bodies, but may be set explicitly for NSData bodies.
|
||||
@property(atomic, assign) BOOL useUploadTask;
|
||||
|
||||
// Indicates that the fetcher is using a session that may be shared with other fetchers.
|
||||
@property(atomic, readonly) BOOL canShareSession;
|
||||
|
||||
// By default, the fetcher allows only secure (https) schemes unless this
|
||||
// property is set, or the GTM_ALLOW_INSECURE_REQUESTS build flag is set.
|
||||
//
|
||||
// For example, during debugging when fetching from a development server that lacks SSL support,
|
||||
// this may be set to @[ @"http" ], or when the fetcher is used to retrieve local files,
|
||||
// this may be set to @[ @"file" ].
|
||||
//
|
||||
// This should be left as nil for release builds to avoid creating the opportunity for
|
||||
// leaking private user behavior and data. If a server is providing insecure URLs
|
||||
// for fetching by the client app, report the problem as server security & privacy bug.
|
||||
//
|
||||
// For builds with the iOS 9/OS X 10.11 and later SDKs, this property is required only when
|
||||
// the app specifies NSAppTransportSecurity/NSAllowsArbitraryLoads in the main bundle's Info.plist.
|
||||
@property(atomic, copy, nullable) NSArray<NSString *> *allowedInsecureSchemes;
|
||||
|
||||
// By default, the fetcher prohibits localhost requests unless this property is set,
|
||||
// or the GTM_ALLOW_INSECURE_REQUESTS build flag is set.
|
||||
//
|
||||
// For localhost requests, the URL scheme is not checked when this property is set.
|
||||
//
|
||||
// For builds with the iOS 9/OS X 10.11 and later SDKs, this property is required only when
|
||||
// the app specifies NSAppTransportSecurity/NSAllowsArbitraryLoads in the main bundle's Info.plist.
|
||||
@property(atomic, assign) BOOL allowLocalhostRequest;
|
||||
|
||||
// By default, the fetcher requires valid server certs. This may be bypassed
|
||||
// temporarily for development against a test server with an invalid cert.
|
||||
@property(atomic, assign) BOOL allowInvalidServerCertificates;
|
||||
|
||||
// Cookie storage object for this fetcher. If nil, the fetcher will use a static cookie
|
||||
// storage instance shared among fetchers. If this fetcher was created by a fetcher service
|
||||
// object, it will be set to use the service object's cookie storage. See Cookies section above for
|
||||
// the full discussion.
|
||||
//
|
||||
// Because as of Jan 2014 standalone instances of NSHTTPCookieStorage do not actually
|
||||
// store any cookies (Radar 15735276) we use our own subclass, GTMSessionCookieStorage,
|
||||
// to hold cookies in memory.
|
||||
@property(atomic, strong, nullable) NSHTTPCookieStorage *cookieStorage;
|
||||
|
||||
// Setting the credential is optional; it is used if the connection receives
|
||||
// an authentication challenge.
|
||||
@property(atomic, strong, nullable) NSURLCredential *credential;
|
||||
|
||||
// Setting the proxy credential is optional; it is used if the connection
|
||||
// receives an authentication challenge from a proxy.
|
||||
@property(atomic, strong, nullable) NSURLCredential *proxyCredential;
|
||||
|
||||
// If body data, body file URL, or body stream provider is not set, then a GET request
|
||||
// method is assumed.
|
||||
@property(atomic, strong, nullable) NSData *bodyData;
|
||||
|
||||
// File to use as the request body. This forces use of an upload task.
|
||||
@property(atomic, strong, nullable) NSURL *bodyFileURL;
|
||||
|
||||
// Length of body to send, expected or actual.
|
||||
@property(atomic, readonly) int64_t bodyLength;
|
||||
|
||||
// The body stream provider may be called repeatedly to provide a body.
|
||||
// Setting a body stream provider forces use of an upload task.
|
||||
@property(atomic, copy, nullable) GTMSessionFetcherBodyStreamProvider bodyStreamProvider;
|
||||
|
||||
#pragma clang diagnostic push
|
||||
// For now retain the existing API surface of accepting a GTMFetcherAuthorizationProtocol
|
||||
// for the authorizer, but the intent is that this will change to take the new
|
||||
// GTMSessionFetcherAuthorizer protocol instead in a future major version update.
|
||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
||||
// Object to add authorization to the request, if needed.
|
||||
//
|
||||
// This may not be changed once beginFetch has been invoked.
|
||||
@property(atomic, strong, nullable) id<GTMFetcherAuthorizationProtocol> authorizer;
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
// The service object that created and monitors this fetcher, if any.
|
||||
@property(atomic, strong) GTMSessionFetcherService *service;
|
||||
|
||||
// The host, if any, used to classify this fetcher in the fetcher service.
|
||||
@property(atomic, copy, nullable) NSString *serviceHost;
|
||||
|
||||
// The priority, if any, used for starting fetchers in the fetcher service.
|
||||
//
|
||||
// Lower values are higher priority; the default is 0, and values may
|
||||
// be negative or positive. This priority affects only the start order of
|
||||
// fetchers that are being delayed by a fetcher service when the running fetchers
|
||||
// exceeds the service's maxRunningFetchersPerHost. A priority of NSIntegerMin will
|
||||
// exempt this fetcher from delay.
|
||||
@property(atomic, assign) NSInteger servicePriority;
|
||||
|
||||
// The delegate's optional didReceiveResponse block may be used to inspect or alter
|
||||
// the session task response.
|
||||
//
|
||||
// This is called on the callback queue.
|
||||
@property(atomic, copy, nullable) GTMSessionFetcherDidReceiveResponseBlock didReceiveResponseBlock;
|
||||
|
||||
// The delegate's optional challenge block may be used to inspect or alter
|
||||
// the session task challenge.
|
||||
//
|
||||
// If this block is not set, the fetcher's default behavior for the NSURLSessionTask
|
||||
// didReceiveChallenge: delegate method is to use the fetcher's respondToChallenge: method
|
||||
// which relies on the fetcher's credential and proxyCredential properties.
|
||||
//
|
||||
// Warning: This may be called repeatedly if the challenge fails. Check
|
||||
// challenge.previousFailureCount to identify repeated invocations.
|
||||
//
|
||||
// This is called on the callback queue.
|
||||
@property(atomic, copy, nullable) GTMSessionFetcherChallengeBlock challengeBlock;
|
||||
|
||||
// The delegate's optional willRedirect block may be used to inspect or alter
|
||||
// the redirection.
|
||||
//
|
||||
// This is called on the callback queue.
|
||||
@property(atomic, copy, nullable) GTMSessionFetcherWillRedirectBlock willRedirectBlock;
|
||||
|
||||
// The optional send progress block reports body bytes uploaded.
|
||||
//
|
||||
// This is called on the callback queue.
|
||||
@property(atomic, copy, nullable) GTMSessionFetcherSendProgressBlock sendProgressBlock;
|
||||
|
||||
// The optional accumulate block may be set by clients wishing to accumulate data
|
||||
// themselves rather than let the fetcher append each buffer to an NSData.
|
||||
//
|
||||
// When this is called with nil data (such as on redirect) the client
|
||||
// should empty its accumulation buffer.
|
||||
//
|
||||
// This is called on the callback queue.
|
||||
@property(atomic, copy, nullable) GTMSessionFetcherAccumulateDataBlock accumulateDataBlock;
|
||||
|
||||
// The optional received progress block may be used to monitor data
|
||||
// received from a data task.
|
||||
//
|
||||
// This is called on the callback queue.
|
||||
@property(atomic, copy, nullable) GTMSessionFetcherReceivedProgressBlock receivedProgressBlock;
|
||||
|
||||
// The delegate's optional downloadProgress block may be used to monitor download
|
||||
// progress in writing to disk.
|
||||
//
|
||||
// This is called on the callback queue.
|
||||
@property(atomic, copy, nullable) GTMSessionFetcherDownloadProgressBlock downloadProgressBlock;
|
||||
|
||||
// The delegate's optional willCacheURLResponse block may be used to alter the cached
|
||||
// NSURLResponse. The user may prevent caching by passing nil to the block's response.
|
||||
//
|
||||
// This is called on the callback queue.
|
||||
@property(atomic, copy, nullable)
|
||||
GTMSessionFetcherWillCacheURLResponseBlock willCacheURLResponseBlock;
|
||||
|
||||
// Enable retrying; see comments at the top of this file. Setting
|
||||
// retryEnabled=YES resets the min and max retry intervals.
|
||||
@property(atomic, assign, getter=isRetryEnabled) BOOL retryEnabled;
|
||||
|
||||
// Retry block is optional for retries.
|
||||
//
|
||||
// If present, this block should call the response block with YES to cause a retry or NO to end the
|
||||
// fetch.
|
||||
// See comments at the top of this file.
|
||||
@property(atomic, copy, nullable) GTMSessionFetcherRetryBlock retryBlock;
|
||||
|
||||
// The optional block for collecting the metrics of the present session.
|
||||
//
|
||||
// This is called on the callback queue.
|
||||
@property(atomic, copy, nullable)
|
||||
GTMSessionFetcherMetricsCollectionBlock metricsCollectionBlock API_AVAILABLE(
|
||||
ios(10.0), macosx(10.12), tvos(10.0), watchos(6.0));
|
||||
|
||||
// Retry intervals must be strictly less than maxRetryInterval, else
|
||||
// they will be limited to maxRetryInterval and no further retries will
|
||||
// be attempted. Setting maxRetryInterval to 0.0 will reset it to the
|
||||
// default value, 60 seconds for downloads and 600 seconds for uploads.
|
||||
@property(atomic, assign) NSTimeInterval maxRetryInterval;
|
||||
|
||||
// Starting retry interval. Setting minRetryInterval to 0.0 will reset it
|
||||
// to a random value between 1.0 and 2.0 seconds. Clients should normally not
|
||||
// set this except for unit testing.
|
||||
@property(atomic, assign) NSTimeInterval minRetryInterval;
|
||||
|
||||
// Multiplier used to increase the interval between retries, typically 2.0.
|
||||
// Clients should not need to set this.
|
||||
@property(atomic, assign) double retryFactor;
|
||||
|
||||
// Number of retries attempted.
|
||||
@property(atomic, readonly) NSUInteger retryCount;
|
||||
|
||||
// Interval delay to precede next retry.
|
||||
@property(atomic, readonly) NSTimeInterval nextRetryInterval;
|
||||
|
||||
#if GTM_BACKGROUND_TASK_FETCHING
|
||||
// Skip use of a UIBackgroundTask, thus requiring fetches to complete when the app is in the
|
||||
// foreground.
|
||||
//
|
||||
// Targets should define GTM_BACKGROUND_TASK_FETCHING to 0 to avoid use of a UIBackgroundTask
|
||||
// on iOS to allow fetches to complete in the background. This property is available when
|
||||
// it's not practical to set the preprocessor define.
|
||||
@property(atomic, assign) BOOL skipBackgroundTask;
|
||||
#endif // GTM_BACKGROUND_TASK_FETCHING
|
||||
|
||||
// Begin fetching the request
|
||||
//
|
||||
// The delegate may optionally implement the callback or pass nil for the selector or handler.
|
||||
//
|
||||
// The delegate and all callback blocks are retained between the beginFetch call until after the
|
||||
// finish callback, or until the fetch is stopped.
|
||||
//
|
||||
// An error is passed to the callback for server statuses 300 or
|
||||
// higher, with the status stored as the error object's code.
|
||||
//
|
||||
// finishedSEL has a signature like:
|
||||
// - (void)fetcher:(GTMSessionFetcher *)fetcher
|
||||
// finishedWithData:(NSData *)data
|
||||
// error:(NSError *)error;
|
||||
//
|
||||
// If the application has specified a destinationFileURL or an accumulateDataBlock
|
||||
// for the fetcher, the data parameter passed to the callback will be nil.
|
||||
|
||||
- (void)beginFetchWithDelegate:(nullable id)delegate didFinishSelector:(nullable SEL)finishedSEL;
|
||||
|
||||
- (void)beginFetchWithCompletionHandler:(nullable GTMSessionFetcherCompletionHandler)handler;
|
||||
|
||||
// Returns YES if this fetcher is in the process of fetching a URL.
|
||||
@property(atomic, readonly, getter=isFetching) BOOL fetching;
|
||||
|
||||
// Cancel the fetch of the request that's currently in progress. The completion handler
|
||||
// will be called with `GTMSessionFetcherErrorUserCancelled` if the property
|
||||
// `stopFetchingTriggersCompletionHandler` is `YES`.
|
||||
- (void)stopFetching;
|
||||
|
||||
// Call callbacks with `GTMSessionFetcherErrorUserCancelled` after a `stopFetching`.
|
||||
// It cannot be changed once the fetcher starts. This should be set to `YES` from
|
||||
// Swift clients before `beginFetch` with `async/await` since the Swift runtime
|
||||
// requires the completion handler to be called.
|
||||
@property(atomic, assign) BOOL stopFetchingTriggersCompletionHandler;
|
||||
|
||||
// A block to be called when the fetch completes.
|
||||
@property(atomic, copy, nullable) GTMSessionFetcherCompletionHandler completionHandler;
|
||||
|
||||
// A block to be called if download resume data becomes available.
|
||||
@property(atomic, strong, nullable) void (^resumeDataBlock)(NSData *);
|
||||
|
||||
// Return the status code from the server response.
|
||||
@property(atomic, readonly) NSInteger statusCode;
|
||||
|
||||
// Return the http headers from the response.
|
||||
@property(atomic, strong, readonly, nullable) NSDictionary<NSString *, NSString *> *responseHeaders;
|
||||
|
||||
// The response, once it's been received.
|
||||
@property(atomic, strong, readonly, nullable) NSURLResponse *response;
|
||||
|
||||
// Bytes downloaded so far.
|
||||
@property(atomic, readonly) int64_t downloadedLength;
|
||||
|
||||
// Buffer of currently-downloaded data, if available.
|
||||
@property(atomic, readonly, strong, nullable) NSData *downloadedData;
|
||||
|
||||
// Local path to which the downloaded file will be moved.
|
||||
//
|
||||
// If a file already exists at the path, it will be overwritten.
|
||||
// Will create the enclosing folders if they are not present.
|
||||
@property(atomic, strong, nullable) NSURL *destinationFileURL;
|
||||
|
||||
// The time this fetcher originally began fetching. This is useful as a time
|
||||
// barrier for ignoring irrelevant fetch notifications or callbacks.
|
||||
@property(atomic, strong, readonly, nullable) NSDate *initialBeginFetchDate;
|
||||
|
||||
// userData is retained solely for the convenience of the client.
|
||||
@property(atomic, strong, nullable) id userData;
|
||||
|
||||
// Stored property values are retained solely for the convenience of the client.
|
||||
@property(atomic, copy, nullable) NSDictionary<NSString *, id> *properties;
|
||||
|
||||
- (void)setProperty:(nullable id)obj
|
||||
forKey:(NSString *)key; // Pass nil for obj to remove the property.
|
||||
- (nullable id)propertyForKey:(NSString *)key;
|
||||
|
||||
- (void)addPropertiesFromDictionary:(NSDictionary<NSString *, id> *)dict;
|
||||
|
||||
// Comments are useful for logging, so are strongly recommended for each fetcher.
|
||||
@property(atomic, copy, nullable) NSString *comment;
|
||||
|
||||
- (void)setCommentWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2);
|
||||
|
||||
// Log of request and response, if logging is enabled
|
||||
@property(atomic, copy, nullable) NSString *log;
|
||||
|
||||
// Callbacks are run on this queue. If none is supplied, the main queue is used.
|
||||
//
|
||||
// CAUTION: This block MUST be a serial queue. Setting a concurrent queue can result in callbacks
|
||||
// being dispatched concurrently, leading events to appear out-of-order.
|
||||
@property(atomic, strong, null_resettable) dispatch_queue_t callbackQueue;
|
||||
|
||||
// The queue used internally by the session to invoke its delegate methods in the fetcher.
|
||||
//
|
||||
// Application callbacks are always called by the fetcher on the callbackQueue above,
|
||||
// not on this queue. Apps should generally not change this queue.
|
||||
//
|
||||
// The default delegate queue is the main queue.
|
||||
//
|
||||
// This value is ignored after the session has been created, so this
|
||||
// property should be set in the fetcher service rather in the fetcher as it applies
|
||||
// to a shared session.
|
||||
@property(atomic, strong, null_resettable) NSOperationQueue *sessionDelegateQueue;
|
||||
|
||||
// DEPRECATED: Callers should use XCTestExpectation instead.
|
||||
//
|
||||
// Spin the run loop or sleep the thread, discarding events, until the fetch has completed.
|
||||
//
|
||||
// This is only for use in testing or in tools without a user interface.
|
||||
//
|
||||
// Note: Synchronous fetches should never be used by shipping apps; they are
|
||||
// sufficient reason for rejection from the app store.
|
||||
//
|
||||
// Returns NO if timed out.
|
||||
- (BOOL)waitForCompletionWithTimeout:(NSTimeInterval)timeoutInSeconds
|
||||
__deprecated_msg("Use XCTestExpectation instead");
|
||||
|
||||
// Test block is optional for testing.
|
||||
//
|
||||
// If present, this block will cause the fetcher to skip starting the session, and instead
|
||||
// use the test block response values when calling the completion handler and delegate code.
|
||||
//
|
||||
// Test code can set this on the fetcher or on the fetcher service. For testing libraries
|
||||
// that use a fetcher without exposing either the fetcher or the fetcher service, the global
|
||||
// method setGlobalTestBlock: will set the block for all fetchers that do not have a test
|
||||
// block set.
|
||||
//
|
||||
// The test code can pass nil for all response parameters to indicate that the fetch
|
||||
// should proceed.
|
||||
//
|
||||
// Applications can exclude test block support by setting GTM_DISABLE_FETCHER_TEST_BLOCK.
|
||||
@property(atomic, copy, nullable) GTMSessionFetcherTestBlock testBlock;
|
||||
|
||||
+ (void)setGlobalTestBlock:(nullable GTMSessionFetcherTestBlock)block;
|
||||
|
||||
// When using the testBlock, |testBlockAccumulateDataChunkCount| is the desired number of chunks to
|
||||
// divide the response data into if the client has streaming enabled. The data will be divided up to
|
||||
// |testBlockAccumulateDataChunkCount| chunks; however, the exact amount may vary depending on the
|
||||
// size of the response data (e.g. a 1-byte response can only be divided into one chunk).
|
||||
@property(atomic, readwrite) NSUInteger testBlockAccumulateDataChunkCount;
|
||||
|
||||
#if GTM_BACKGROUND_TASK_FETCHING
|
||||
// For testing or to override UIApplication invocations, apps may specify an alternative
|
||||
// target for messages to UIApplication.
|
||||
+ (void)setSubstituteUIApplication:(nullable id<GTMUIApplicationProtocol>)substituteUIApplication;
|
||||
+ (nullable id<GTMUIApplicationProtocol>)substituteUIApplication;
|
||||
#endif // GTM_BACKGROUND_TASK_FETCHING
|
||||
|
||||
// Exposed for testing.
|
||||
+ (GTMSessionCookieStorage *)staticCookieStorage;
|
||||
+ (BOOL)appAllowsInsecureRequests;
|
||||
|
||||
#if STRIP_GTM_FETCH_LOGGING
|
||||
// If logging is stripped, provide a stub for the main method
|
||||
// for controlling logging.
|
||||
+ (void)setLoggingEnabled:(BOOL)flag;
|
||||
+ (BOOL)isLoggingEnabled;
|
||||
|
||||
#else
|
||||
|
||||
// These methods let an application log specific body text, such as the text description of a binary
|
||||
// request or response. The application should set the fetcher to defer response body logging until
|
||||
// the response has been received and the log response body has been set by the app. For example:
|
||||
//
|
||||
// fetcher.logRequestBody = [binaryObject stringDescription];
|
||||
// fetcher.deferResponseBodyLogging = YES;
|
||||
// [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) {
|
||||
// if (error == nil) {
|
||||
// fetcher.logResponseBody = [[[MyThing alloc] initWithData:data] stringDescription];
|
||||
// }
|
||||
// fetcher.deferResponseBodyLogging = NO;
|
||||
// }];
|
||||
|
||||
@property(atomic, copy, nullable) NSString *logRequestBody;
|
||||
@property(atomic, assign) BOOL deferResponseBodyLogging;
|
||||
@property(atomic, copy, nullable) NSString *logResponseBody;
|
||||
|
||||
// Internal logging support.
|
||||
@property(atomic, readonly) NSData *loggedStreamData;
|
||||
@property(atomic, assign) BOOL hasLoggedError;
|
||||
@property(atomic, strong, nullable) NSURL *redirectedFromURL;
|
||||
- (void)appendLoggedStreamData:(NSData *)dataToAdd;
|
||||
- (void)clearLoggedStreamData;
|
||||
|
||||
#endif // STRIP_GTM_FETCH_LOGGING
|
||||
|
||||
@end
|
||||
|
||||
// Until we can just instantiate NSHTTPCookieStorage for local use, we'll
|
||||
// implement all the public methods ourselves. This stores cookies only in
|
||||
// memory. Additional methods are provided for testing.
|
||||
//
|
||||
// iOS 9/OS X 10.11 added +[NSHTTPCookieStorage sharedCookieStorageForGroupContainerIdentifier:]
|
||||
// which may also be used to create cookie storage.
|
||||
@interface GTMSessionCookieStorage : NSHTTPCookieStorage
|
||||
|
||||
// Add the array off cookies to the storage, replacing duplicates.
|
||||
// Also removes expired cookies from the storage.
|
||||
- (void)setCookies:(nullable NSArray<NSHTTPCookie *> *)cookies;
|
||||
|
||||
- (void)removeAllCookies;
|
||||
|
||||
@end
|
||||
|
||||
// Macros to monitor synchronization blocks in debug builds.
|
||||
// These report problems using GTMSessionCheckDebug.
|
||||
//
|
||||
// GTMSessionMonitorSynchronized Start monitoring a top-level-only
|
||||
// @sync scope.
|
||||
// GTMSessionMonitorRecursiveSynchronized Start monitoring a top-level or
|
||||
// recursive @sync scope.
|
||||
// GTMSessionCheckSynchronized Verify that the current execution
|
||||
// is inside a @sync scope.
|
||||
// GTMSessionCheckNotSynchronized Verify that the current execution
|
||||
// is not inside a @sync scope.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// - (void)myExternalMethod {
|
||||
// @synchronized(self) {
|
||||
// GTMSessionMonitorSynchronized(self)
|
||||
//
|
||||
// - (void)myInternalMethod {
|
||||
// GTMSessionCheckSynchronized(self);
|
||||
//
|
||||
// - (void)callMyCallbacks {
|
||||
// GTMSessionCheckNotSynchronized(self);
|
||||
//
|
||||
// GTMSessionCheckNotSynchronized is available for verifying the code isn't
|
||||
// in a deadlockable @sync state when posting notifications and invoking
|
||||
// callbacks. Don't use GTMSessionCheckNotSynchronized immediately before a
|
||||
// @sync scope; the normal recursiveness check of GTMSessionMonitorSynchronized
|
||||
// can catch those.
|
||||
|
||||
#ifdef __OBJC__
|
||||
// If asserts are entirely no-ops, the synchronization monitor is just a bunch
|
||||
// of counting code that doesn't report exceptional circumstances in any way.
|
||||
// Only build the synchronization monitor code if NS_BLOCK_ASSERTIONS is not
|
||||
// defined or asserts are being logged instead.
|
||||
#if DEBUG && (!defined(NS_BLOCK_ASSERTIONS) || GTMSESSION_ASSERT_AS_LOG)
|
||||
#define __GTMSessionMonitorSynchronizedVariableInner(varname, counter) varname##counter
|
||||
#define __GTMSessionMonitorSynchronizedVariable(varname, counter) \
|
||||
__GTMSessionMonitorSynchronizedVariableInner(varname, counter)
|
||||
|
||||
#define GTMSessionMonitorSynchronized(obj) \
|
||||
NS_VALID_UNTIL_END_OF_SCOPE id __GTMSessionMonitorSynchronizedVariable(__monitor, __COUNTER__) = \
|
||||
[[GTMSessionSyncMonitorInternal alloc] initWithSynchronizationObject:obj \
|
||||
allowRecursive:NO \
|
||||
functionName:__func__]
|
||||
|
||||
#define GTMSessionMonitorRecursiveSynchronized(obj) \
|
||||
NS_VALID_UNTIL_END_OF_SCOPE id __GTMSessionMonitorSynchronizedVariable(__monitor, __COUNTER__) = \
|
||||
[[GTMSessionSyncMonitorInternal alloc] initWithSynchronizationObject:obj \
|
||||
allowRecursive:YES \
|
||||
functionName:__func__]
|
||||
|
||||
#define GTMSessionCheckSynchronized(obj) \
|
||||
{ \
|
||||
GTMSESSION_ASSERT_DEBUG( \
|
||||
[GTMSessionSyncMonitorInternal functionsHoldingSynchronizationOnObject:obj], \
|
||||
@"GTMSessionCheckSynchronized(" #obj ") failed: not sync'd" \
|
||||
@" on " #obj " in %s. Call stack:\n%@", \
|
||||
__func__, [NSThread callStackSymbols]); \
|
||||
}
|
||||
|
||||
#define GTMSessionCheckNotSynchronized(obj) \
|
||||
{ \
|
||||
GTMSESSION_ASSERT_DEBUG( \
|
||||
![GTMSessionSyncMonitorInternal functionsHoldingSynchronizationOnObject:obj], \
|
||||
@"GTMSessionCheckNotSynchronized(" #obj ") failed: was sync'd" \
|
||||
@" on " #obj " in %s by %@. Call stack:\n%@", \
|
||||
__func__, [GTMSessionSyncMonitorInternal functionsHoldingSynchronizationOnObject:obj], \
|
||||
[NSThread callStackSymbols]); \
|
||||
}
|
||||
|
||||
// GTMSessionSyncMonitorInternal is a private class that keeps track of the
|
||||
// beginning and end of synchronized scopes.
|
||||
//
|
||||
// This class should not be used directly, but only via the
|
||||
// GTMSessionMonitorSynchronized macro.
|
||||
@interface GTMSessionSyncMonitorInternal : NSObject
|
||||
- (instancetype)initWithSynchronizationObject:(id)object
|
||||
allowRecursive:(BOOL)allowRecursive
|
||||
functionName:(const char *)functionName;
|
||||
// Return the names of the functions that hold sync on the object, or nil if none.
|
||||
+ (nullable NSArray *)functionsHoldingSynchronizationOnObject:(id)object;
|
||||
@end
|
||||
|
||||
#else
|
||||
#define GTMSessionMonitorSynchronized(obj) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define GTMSessionMonitorRecursiveSynchronized(obj) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define GTMSessionCheckSynchronized(obj) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define GTMSessionCheckNotSynchronized(obj) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif // !DEBUG
|
||||
#endif // __OBJC__
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
105
Pods/GTMSessionFetcher/Sources/Core/Public/GTMSessionFetcher/GTMSessionFetcherLogging.h
generated
Normal file
105
Pods/GTMSessionFetcher/Sources/Core/Public/GTMSessionFetcher/GTMSessionFetcherLogging.h
generated
Normal file
@@ -0,0 +1,105 @@
|
||||
/* Copyright 2014 Google Inc. All rights reserved.
|
||||
*
|
||||
* 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 "GTMSessionFetcher/GTMSessionFetcher.h"
|
||||
|
||||
// GTM HTTP Logging
|
||||
//
|
||||
// All traffic using GTMSessionFetcher can be easily logged. Call
|
||||
//
|
||||
// [GTMSessionFetcher setLoggingEnabled:YES];
|
||||
//
|
||||
// to begin generating log files.
|
||||
//
|
||||
// Unless explicitly set by the application using +setLoggingDirectory:,
|
||||
// logs are put into a default directory, located at:
|
||||
// * macOS: ~/Desktop/GTMHTTPDebugLogs
|
||||
// * iOS simulator: ~/GTMHTTPDebugLogs (in application sandbox)
|
||||
// * iOS device: ~/Documents/GTMHTTPDebugLogs (in application sandbox)
|
||||
//
|
||||
// Tip: use the Finder's "Sort By Date" to find the most recent logs.
|
||||
//
|
||||
// Each run of an application gets a separate set of log files. An html
|
||||
// file is generated to simplify browsing the run's http transactions.
|
||||
// The html file includes javascript links for inline viewing of uploaded
|
||||
// and downloaded data.
|
||||
//
|
||||
// A symlink is created in the logs folder to simplify finding the html file
|
||||
// for the latest run of the application; the symlink is called
|
||||
//
|
||||
// AppName_http_log_newest.html
|
||||
//
|
||||
// Each fetcher may be given a comment to be inserted as a label in the logs,
|
||||
// such as
|
||||
// [fetcher setCommentWithFormat:@"retrieve item %@", itemName];
|
||||
//
|
||||
// Projects may define STRIP_GTM_FETCH_LOGGING to remove logging code.
|
||||
|
||||
#if !STRIP_GTM_FETCH_LOGGING
|
||||
|
||||
@interface GTMSessionFetcher (GTMSessionFetcherLogging)
|
||||
|
||||
// Note: on macOS the default logs directory is ~/Desktop/GTMHTTPDebugLogs; on
|
||||
// iOS simulators it will be the ~/GTMHTTPDebugLogs (in the app sandbox); on
|
||||
// iOS devices it will be in ~/Documents/GTMHTTPDebugLogs (in the app sandbox).
|
||||
// These directories will be created as needed, and are excluded from backups
|
||||
// to iCloud and iTunes.
|
||||
//
|
||||
// If a custom directory is set, the directory should already exist. It is
|
||||
// the application's responsibility to exclude any custom directory from
|
||||
// backups, if desired.
|
||||
+ (void)setLoggingDirectory:(NSString *)path;
|
||||
+ (NSString *)loggingDirectory;
|
||||
|
||||
// client apps can turn logging on and off
|
||||
+ (void)setLoggingEnabled:(BOOL)isLoggingEnabled;
|
||||
+ (BOOL)isLoggingEnabled;
|
||||
|
||||
// client apps can turn off logging to a file if they want to only check
|
||||
// the fetcher's log property
|
||||
+ (void)setLoggingToFileEnabled:(BOOL)isLoggingToFileEnabled;
|
||||
+ (BOOL)isLoggingToFileEnabled;
|
||||
|
||||
// client apps can optionally specify process name and date string used in
|
||||
// log file names
|
||||
+ (void)setLoggingProcessName:(NSString *)processName;
|
||||
+ (NSString *)loggingProcessName;
|
||||
|
||||
+ (void)setLoggingDateStamp:(NSString *)dateStamp;
|
||||
+ (NSString *)loggingDateStamp;
|
||||
|
||||
// client apps can specify the directory for the log for this specific run:
|
||||
//
|
||||
// [GTMSessionFetcher setLogDirectoryForCurrentRun:logDirectoryPath];
|
||||
//
|
||||
// Setting this overrides the logging directory, process name, and date stamp when writing
|
||||
// the log file.
|
||||
+ (void)setLogDirectoryForCurrentRun:(NSString *)logDirectoryForCurrentRun;
|
||||
+ (NSString *)logDirectoryForCurrentRun;
|
||||
|
||||
// internal; called by fetcher
|
||||
- (void)logFetchWithError:(NSError *)error;
|
||||
- (NSInputStream *)loggedInputStreamForInputStream:(NSInputStream *)inputStream;
|
||||
- (GTMSessionFetcherBodyStreamProvider)loggedStreamProviderForStreamProvider:
|
||||
(GTMSessionFetcherBodyStreamProvider)streamProvider;
|
||||
|
||||
// internal; accessors useful for viewing logs
|
||||
+ (NSString *)processNameLogPrefix;
|
||||
+ (NSString *)symlinkNameSuffix;
|
||||
+ (NSString *)htmlFileName;
|
||||
|
||||
@end
|
||||
|
||||
#endif // !STRIP_GTM_FETCH_LOGGING
|
||||
230
Pods/GTMSessionFetcher/Sources/Core/Public/GTMSessionFetcher/GTMSessionFetcherService.h
generated
Normal file
230
Pods/GTMSessionFetcher/Sources/Core/Public/GTMSessionFetcher/GTMSessionFetcherService.h
generated
Normal file
@@ -0,0 +1,230 @@
|
||||
/* Copyright 2014 Google Inc. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// For best performance and convenient usage, fetchers should be generated by a common
|
||||
// GTMSessionFetcherService instance, like
|
||||
//
|
||||
// _fetcherService = [[GTMSessionFetcherService alloc] init];
|
||||
// GTMSessionFetcher* myFirstFetcher = [_fetcherService fetcherWithRequest:request1];
|
||||
// GTMSessionFetcher* mySecondFetcher = [_fetcherService fetcherWithRequest:request2];
|
||||
|
||||
#import "GTMSessionFetcher/GTMSessionFetcher.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// Notifications.
|
||||
|
||||
// This notification indicates a reusable session has become invalid. It is intended mainly for the
|
||||
// service's unit tests.
|
||||
//
|
||||
// The notification object is the fetcher service.
|
||||
// The invalid session is provided via the userInfo kGTMSessionFetcherServiceSessionKey key.
|
||||
extern NSString *const kGTMSessionFetcherServiceSessionBecameInvalidNotification;
|
||||
extern NSString *const kGTMSessionFetcherServiceSessionKey;
|
||||
|
||||
@interface GTMSessionFetcherService : NSObject <GTMSessionFetcherServiceProtocol>
|
||||
|
||||
// Queues of delayed and running fetchers. Each dictionary contains arrays
|
||||
// of GTMSessionFetcher *fetchers, keyed by NSString *host
|
||||
@property(atomic, strong, readonly, nullable)
|
||||
NSDictionary<NSString *, NSArray *> *delayedFetchersByHost;
|
||||
@property(atomic, strong, readonly, nullable)
|
||||
NSDictionary<NSString *, NSArray *> *runningFetchersByHost;
|
||||
|
||||
// A max value of 0 means no fetchers should be delayed.
|
||||
// The default limit is 10 simultaneous fetchers targeting each host.
|
||||
// This does not apply to fetchers whose useBackgroundSession property is YES. Since services are
|
||||
// not resurrected on an app relaunch, delayed fetchers would effectively be abandoned.
|
||||
@property(atomic, assign) NSUInteger maxRunningFetchersPerHost;
|
||||
|
||||
// Properties to be applied to each fetcher; see GTMSessionFetcher.h for descriptions
|
||||
@property(atomic, strong, nullable) NSURLSessionConfiguration *configuration;
|
||||
@property(atomic, copy, nullable) GTMSessionFetcherConfigurationBlock configurationBlock;
|
||||
@property(atomic, strong, nullable) NSHTTPCookieStorage *cookieStorage;
|
||||
@property(atomic, strong, null_resettable) dispatch_queue_t callbackQueue;
|
||||
@property(atomic, copy, nullable) GTMSessionFetcherChallengeBlock challengeBlock;
|
||||
@property(atomic, strong, nullable) NSURLCredential *credential;
|
||||
@property(atomic, strong) NSURLCredential *proxyCredential;
|
||||
@property(atomic, copy, nullable) NSArray<NSString *> *allowedInsecureSchemes;
|
||||
@property(atomic, assign) BOOL allowLocalhostRequest;
|
||||
@property(atomic, assign) BOOL allowInvalidServerCertificates;
|
||||
@property(atomic, assign, getter=isRetryEnabled) BOOL retryEnabled;
|
||||
@property(atomic, copy, nullable) GTMSessionFetcherRetryBlock retryBlock;
|
||||
@property(atomic, assign) NSTimeInterval maxRetryInterval;
|
||||
@property(atomic, assign) NSTimeInterval minRetryInterval;
|
||||
@property(atomic, copy, nullable) NSDictionary<NSString *, id> *properties;
|
||||
@property(atomic, copy, nullable)
|
||||
GTMSessionFetcherMetricsCollectionBlock metricsCollectionBlock API_AVAILABLE(
|
||||
ios(10.0), macosx(10.12), tvos(10.0), watchos(6.0));
|
||||
|
||||
#if GTM_BACKGROUND_TASK_FETCHING
|
||||
@property(atomic, assign) BOOL skipBackgroundTask;
|
||||
#endif
|
||||
|
||||
// An optional provider to calculate the User-Agent string on demand. If non-nil and
|
||||
// an HTTP header field for User-Agent is not set, this is queried before sending out
|
||||
// the network request for the User-Agent string.
|
||||
@property(atomic, strong, nullable) id<GTMUserAgentProvider> userAgentProvider;
|
||||
|
||||
// A default useragent of GTMFetcherStandardUserAgentString(nil) will be given to each fetcher
|
||||
// created by this service unless the request already has a user-agent header set.
|
||||
// This default will be added starting with builds with the SDKs for OS X 10.11 and iOS 9.
|
||||
//
|
||||
// To use the configuration's default user agent, set this property to nil.
|
||||
@property(atomic, copy, nullable) NSString *userAgent;
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
||||
// The authorizer to attach to the created fetchers. If a specific fetcher should
|
||||
// not authorize its requests, the fetcher's authorizer property may be set to nil
|
||||
// before the fetch begins.
|
||||
@property(atomic, strong, nullable) id<GTMFetcherAuthorizationProtocol> authorizer;
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
@property(atomic, readonly, strong, nullable) NSOperationQueue *delegateQueue;
|
||||
|
||||
// Delegate queue used by the session when calling back to the fetcher. The default
|
||||
// is the main queue. Changing this does not affect the queue used to call back to the
|
||||
// application; that is specified by the callbackQueue property above.
|
||||
@property(atomic, strong, null_resettable) NSOperationQueue *sessionDelegateQueue;
|
||||
|
||||
// When enabled, indicates the same session should be used by subsequent fetchers.
|
||||
//
|
||||
// This is enabled by default.
|
||||
@property(atomic, assign) BOOL reuseSession;
|
||||
|
||||
// Sets the delay until an unused session is invalidated.
|
||||
// The default interval is 60 seconds.
|
||||
//
|
||||
// If the interval is set to 0, then any reused session is not invalidated except by
|
||||
// explicitly invoking -resetSession. Be aware that setting the interval to 0 thus
|
||||
// causes the session's delegate to be retained until the session is explicitly reset.
|
||||
@property(atomic, assign) NSTimeInterval unusedSessionTimeout;
|
||||
|
||||
// If shouldReuseSession is enabled, this will force creation of a new session when future
|
||||
// fetchers begin.
|
||||
- (void)resetSession;
|
||||
|
||||
// Sets the callback queue, specifying that the provided queue is a concurrent queue.
|
||||
//
|
||||
// When a concurrent queue is explicitly provided via this setter, then each new fetcher
|
||||
// instance created by the service will be provided a new serial queue targeting the
|
||||
// concurrent callback queue; this will ensure callbacks for each instance are executed
|
||||
// in order, while callbacks from separate fetcher instances are not blocked by each other.
|
||||
//
|
||||
// The service behavior when resetting the callback queue after providing a concurrent
|
||||
// queue is unspecified.
|
||||
- (void)setConcurrentCallbackQueue:(dispatch_queue_t)queue;
|
||||
|
||||
// Create a fetcher
|
||||
//
|
||||
// These methods will return a fetcher. If successfully created, the connection
|
||||
// will hold a strong reference to it for the life of the connection as well.
|
||||
// So the caller doesn't have to hold onto the fetcher explicitly unless they
|
||||
// want to be able to monitor or cancel it.
|
||||
- (GTMSessionFetcher *)fetcherWithRequest:(NSURLRequest *)request;
|
||||
- (GTMSessionFetcher *)fetcherWithURL:(NSURL *)requestURL;
|
||||
- (GTMSessionFetcher *)fetcherWithURLString:(NSString *)requestURLString;
|
||||
|
||||
// Common method for fetcher creation.
|
||||
//
|
||||
// -fetcherWithRequest:fetcherClass: may be overridden to customize creation of
|
||||
// fetchers. This is the ONLY method in the GTMSessionFetcher library intended to
|
||||
// be overridden.
|
||||
- (id)fetcherWithRequest:(NSURLRequest *)request fetcherClass:(Class)fetcherClass;
|
||||
|
||||
- (BOOL)isDelayingFetcher:(GTMSessionFetcher *)fetcher;
|
||||
|
||||
- (NSUInteger)numberOfFetchers; // running + delayed fetchers
|
||||
- (NSUInteger)numberOfRunningFetchers;
|
||||
- (NSUInteger)numberOfDelayedFetchers;
|
||||
|
||||
// Return a list of all running or delayed fetchers. This includes fetchers created
|
||||
// by the service which have been started and have not yet stopped.
|
||||
//
|
||||
// Returns an array of fetcher objects, or nil if none.
|
||||
- (nullable NSArray<GTMSessionFetcher *> *)issuedFetchers;
|
||||
|
||||
// Search for running or delayed fetchers with the specified URL.
|
||||
//
|
||||
// Returns an array of fetcher objects found, or nil if none found.
|
||||
- (nullable NSArray<GTMSessionFetcher *> *)issuedFetchersWithRequestURL:(NSURL *)requestURL;
|
||||
|
||||
- (void)stopAllFetchers;
|
||||
|
||||
// All decorators added to the service.
|
||||
@property(atomic, readonly, strong, nullable) NSArray<id<GTMFetcherDecoratorProtocol>> *decorators;
|
||||
|
||||
// Holds a weak reference to `decorator`. When creating a fetcher via
|
||||
// `-fetcherWithRequest:fetcherClass:`, each registered `decorator` can inspect and potentially
|
||||
// change the fetcher's request before it starts. Decorators are invoked in the order in which
|
||||
// they are passed to this method.
|
||||
- (void)addDecorator:(id<GTMFetcherDecoratorProtocol>)decorator;
|
||||
|
||||
// Removes a `decorator` previously passed to `-removeDecorator:`.
|
||||
- (void)removeDecorator:(id<GTMFetcherDecoratorProtocol>)decorator;
|
||||
|
||||
// The testBlock can inspect its fetcher parameter's request property to
|
||||
// determine which fetcher is being faked.
|
||||
@property(atomic, copy, nullable) GTMSessionFetcherTestBlock testBlock;
|
||||
|
||||
@end
|
||||
|
||||
@interface GTMSessionFetcherService (FetcherCallbacks)
|
||||
// Checks whether the fetcher should delay starting to avoid overloading the host.
|
||||
- (BOOL)fetcherShouldBeginFetching:(nonnull GTMSessionFetcher *)fetcher;
|
||||
|
||||
// Notifies the service that the fetcher did begin fetching.
|
||||
- (void)fetcherDidBeginFetching:(nonnull GTMSessionFetcher *)fetcher;
|
||||
|
||||
// Notifies the service that the fetcher has stopped fetching.
|
||||
- (void)fetcherDidStop:(nonnull GTMSessionFetcher *)fetcher;
|
||||
@end
|
||||
|
||||
@interface GTMSessionFetcherService (TestingSupport)
|
||||
|
||||
// Convenience methods to create a fetcher service for testing.
|
||||
//
|
||||
// Fetchers generated by this mock fetcher service will not perform any
|
||||
// network operation, but will invoke callbacks and provide the supplied data
|
||||
// or error to the completion handler.
|
||||
//
|
||||
// You can make more customized mocks by setting the test block property of the service
|
||||
// or fetcher; the test block can inspect the fetcher's request or other properties.
|
||||
//
|
||||
// See the description of the testBlock property below.
|
||||
+ (instancetype)mockFetcherServiceWithFakedData:(nullable NSData *)fakedDataOrNil
|
||||
fakedError:(nullable NSError *)fakedErrorOrNil;
|
||||
+ (instancetype)mockFetcherServiceWithFakedData:(nullable NSData *)fakedDataOrNil
|
||||
fakedResponse:(NSHTTPURLResponse *)fakedResponse
|
||||
fakedError:(nullable NSError *)fakedErrorOrNil;
|
||||
|
||||
// DEPRECATED: Callers should use XCTestExpectation instead.
|
||||
//
|
||||
// Spin the run loop and discard events (or, if not on the main thread, just sleep the thread)
|
||||
// until all running and delayed fetchers have completed.
|
||||
//
|
||||
// This is only for use in testing or in tools without a user interface.
|
||||
//
|
||||
// Synchronous fetches should never be done by shipping apps; they are
|
||||
// sufficient reason for rejection from the app store.
|
||||
//
|
||||
// Returns NO if timed out.
|
||||
- (BOOL)waitForCompletionOfAllFetchersWithTimeout:(NSTimeInterval)timeoutInSeconds
|
||||
__deprecated_msg("Use XCTestExpectation instead");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
179
Pods/GTMSessionFetcher/Sources/Core/Public/GTMSessionFetcher/GTMSessionUploadFetcher.h
generated
Normal file
179
Pods/GTMSessionFetcher/Sources/Core/Public/GTMSessionFetcher/GTMSessionUploadFetcher.h
generated
Normal file
@@ -0,0 +1,179 @@
|
||||
/* Copyright 2014 Google Inc. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// GTMSessionUploadFetcher implements Google's resumable upload protocol.
|
||||
|
||||
//
|
||||
// This subclass of GTMSessionFetcher simulates the series of fetches
|
||||
// needed for chunked upload as a single fetch operation.
|
||||
//
|
||||
// Protocol document: TBD
|
||||
//
|
||||
// To the client, the only fetcher that exists is this class; the subsidiary
|
||||
// fetchers needed for uploading chunks are not visible (though the most recent
|
||||
// chunk fetcher may be accessed via the -activeFetcher or -chunkFetcher methods, and
|
||||
// -responseHeaders and -statusCode reflect results from the most recent chunk
|
||||
// fetcher.)
|
||||
//
|
||||
// Chunk fetchers are discarded as soon as they have completed.
|
||||
//
|
||||
// The protocol also allows for a cancellation notification request to be sent to the
|
||||
// server to allow discarding of the currently uploaded data and this will be sent
|
||||
// automatically upon calling stopFetching if the upload has already started.
|
||||
//
|
||||
// Note: Unlike the fetcher superclass, the methods of GTMSessionUploadFetcher should
|
||||
// only be used from the main thread until further work is done to make this subclass
|
||||
// thread-safe.
|
||||
|
||||
#import "GTMSessionFetcher/GTMSessionFetcher.h"
|
||||
#import "GTMSessionFetcher/GTMSessionFetcherService.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// The value to use for file size parameters when the file size is not yet known.
|
||||
extern int64_t const kGTMSessionUploadFetcherUnknownFileSize;
|
||||
|
||||
// Unless an application knows it needs a smaller chunk size, it should use the standard
|
||||
// chunk size, which sends the entire file as a single chunk to minimize upload overhead.
|
||||
// Setting an explicit chunk size that comfortably fits in memory is advisable for large
|
||||
// uploads.
|
||||
extern int64_t const kGTMSessionUploadFetcherStandardChunkSize;
|
||||
|
||||
// When uploading requires data buffer allocations (such as uploading from an NSData or
|
||||
// an NSFileHandle) this is the maximum buffer size that will be created by the fetcher.
|
||||
extern int64_t const kGTMSessionUploadFetcherMaximumDemandBufferSize;
|
||||
|
||||
// Notification that the upload location URL was provided by the server.
|
||||
extern NSString *const kGTMSessionFetcherUploadLocationObtainedNotification;
|
||||
// Notification that the exponential backoff for upload has started.
|
||||
extern NSString *const kGTMSessionFetcherUploadInitialBackoffStartedNotification;
|
||||
|
||||
// Block to provide data during uploads.
|
||||
//
|
||||
// Response data may be allocated with dataWithBytesNoCopy:length:freeWhenDone: for efficiency,
|
||||
// and released after the response block returns.
|
||||
//
|
||||
// If the length of the file being uploaded is unknown or already set, send
|
||||
// kGTMSessionUploadFetcherUnknownFileSize for |fullUploadLength|. Otherwise, set |fullUploadLength|
|
||||
// to its proper value.
|
||||
//
|
||||
// Pass nil as the data (and optionally an NSError) for a failure.
|
||||
typedef void (^GTMSessionUploadFetcherDataProviderResponse)(NSData *_Nullable data,
|
||||
int64_t fullUploadLength,
|
||||
NSError *_Nullable error);
|
||||
// Do not call the response with an NSData object with less data than the requested length unless
|
||||
// you are passing the fullUploadLength to the fetcher for the first time and it is the last chunk
|
||||
// of data in the file being uploaded.
|
||||
typedef void (^GTMSessionUploadFetcherDataProvider)(
|
||||
int64_t offset, int64_t length, GTMSessionUploadFetcherDataProviderResponse response);
|
||||
|
||||
// Block to be notified about the final status of the cancellation request started in stopFetching.
|
||||
//
|
||||
// |fetcher| will be the cancel request that was sent to the server, or nil if stopFetching is not
|
||||
// going to send a cancel request. If |fetcher| is provided, the other parameters correspond to the
|
||||
// completion handler of the cancellation request fetcher.
|
||||
typedef void (^GTMSessionUploadFetcherCancellationHandler)(GTMSessionFetcher *_Nullable fetcher,
|
||||
NSData *_Nullable data,
|
||||
NSError *_Nullable error);
|
||||
|
||||
@interface GTMSessionUploadFetcher : GTMSessionFetcher
|
||||
|
||||
// Create an upload fetcher specifying either the request or the resume location URL,
|
||||
// then set an upload data source using one of these:
|
||||
//
|
||||
// setUploadFileURL:
|
||||
// setUploadDataLength:provider:
|
||||
// setUploadFileHandle:
|
||||
// setUploadData:
|
||||
|
||||
+ (instancetype)uploadFetcherWithRequest:(NSURLRequest *)request
|
||||
uploadMIMEType:(NSString *)uploadMIMEType
|
||||
chunkSize:(int64_t)chunkSize
|
||||
fetcherService:(nullable GTMSessionFetcherService *)fetcherServiceOrNil;
|
||||
|
||||
// Allows cellular access.
|
||||
+ (instancetype)uploadFetcherWithLocation:(nullable NSURL *)uploadLocationURL
|
||||
uploadMIMEType:(NSString *)uploadMIMEType
|
||||
chunkSize:(int64_t)chunkSize
|
||||
fetcherService:(nullable GTMSessionFetcherService *)fetcherServiceOrNil;
|
||||
|
||||
+ (instancetype)uploadFetcherWithLocation:(nullable NSURL *)uploadLocationURL
|
||||
uploadMIMEType:(NSString *)uploadMIMEType
|
||||
chunkSize:(int64_t)chunkSize
|
||||
allowsCellularAccess:(BOOL)allowsCellularAccess
|
||||
fetcherService:(nullable GTMSessionFetcherService *)fetcherServiceOrNil;
|
||||
|
||||
// Allows dataProviders for files of unknown length. Pass kGTMSessionUploadFetcherUnknownFileSize as
|
||||
// |fullLength| if the length is unknown.
|
||||
- (void)setUploadDataLength:(int64_t)fullLength
|
||||
provider:(nullable GTMSessionUploadFetcherDataProvider)block;
|
||||
|
||||
+ (NSArray *)uploadFetchersForBackgroundSessions;
|
||||
+ (nullable instancetype)uploadFetcherForSessionIdentifier:(NSString *)sessionIdentifier;
|
||||
|
||||
- (void)pauseFetching;
|
||||
- (void)resumeFetching;
|
||||
- (BOOL)isPaused;
|
||||
|
||||
@property(atomic, strong, nullable) NSURL *uploadLocationURL;
|
||||
@property(atomic, strong, nullable) NSData *uploadData;
|
||||
@property(atomic, strong, nullable) NSURL *uploadFileURL;
|
||||
@property(atomic, strong, nullable) NSFileHandle *uploadFileHandle;
|
||||
@property(atomic, copy, readonly, nullable) GTMSessionUploadFetcherDataProvider uploadDataProvider;
|
||||
@property(atomic, copy) NSString *uploadMIMEType;
|
||||
@property(atomic, readonly, assign) int64_t chunkSize;
|
||||
@property(atomic, readonly, assign) int64_t currentOffset;
|
||||
@property(atomic, assign) double uploadRetryFactor;
|
||||
@property(atomic, assign) NSTimeInterval maxUploadRetryInterval;
|
||||
@property(atomic, assign) NSTimeInterval minUploadRetryInterval;
|
||||
|
||||
// Reflects the original NSURLRequest's @c allowCellularAccess property.
|
||||
@property(atomic, readonly, assign) BOOL allowsCellularAccess;
|
||||
|
||||
// The fetcher for the current data chunk, if any
|
||||
@property(atomic, strong, nullable) GTMSessionFetcher *chunkFetcher;
|
||||
|
||||
// The active fetcher is the current chunk fetcher, or the upload fetcher itself
|
||||
// if no chunk fetcher has yet been created.
|
||||
@property(atomic, readonly) GTMSessionFetcher *activeFetcher;
|
||||
|
||||
// The last request made by an active fetcher. Useful for testing.
|
||||
@property(atomic, readonly, nullable) NSURLRequest *lastChunkRequest;
|
||||
|
||||
// The status code from the most recently-completed fetch.
|
||||
@property(atomic, assign) NSInteger statusCode;
|
||||
|
||||
// Invoked as part of the stop fetching process. Invoked immediately if there is no upload in
|
||||
// progress, otherwise invoked with the results of the attempt to notify the server that the
|
||||
// upload will not continue.
|
||||
//
|
||||
// Unlike other callbacks, since this is related specifically to the stopFetching flow it is not
|
||||
// cleared by stopFetching. It will instead clear itself after it is invoked or if the completion
|
||||
// has occured before stopFetching is called.
|
||||
@property(atomic, copy, nullable) GTMSessionUploadFetcherCancellationHandler cancellationHandler;
|
||||
|
||||
// Exposed for testing only.
|
||||
@property(atomic, readonly, nullable) dispatch_queue_t delegateCallbackQueue;
|
||||
@property(atomic, readonly, nullable) GTMSessionFetcherCompletionHandler delegateCompletionHandler;
|
||||
|
||||
@end
|
||||
|
||||
@interface GTMSessionFetcher (GTMSessionUploadFetcherMethods)
|
||||
|
||||
@property(readonly, nullable) GTMSessionUploadFetcher *parentUploadFetcher;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Reference in New Issue
Block a user