PageRenderTime 43ms CodeModel.GetById 17ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/core/externals/update-engine/externals/gdata-objectivec-client/Source/HTTPFetcher/GTMHTTPFetcher.h

http://macfuse.googlecode.com/
C++ Header | 767 lines | 239 code | 106 blank | 422 comment | 1 complexity | 9f8ba41fffe2e8c94700c35468c04fb9 MD5 | raw file
  1/* Copyright (c) 2011 Google Inc.
  2 *
  3 * Licensed under the Apache License, Version 2.0 (the "License");
  4 * you may not use this file except in compliance with the License.
  5 * You may obtain a copy of the License at
  6 *
  7 *     http://www.apache.org/licenses/LICENSE-2.0
  8 *
  9 * Unless required by applicable law or agreed to in writing, software
 10 * distributed under the License is distributed on an "AS IS" BASIS,
 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 * See the License for the specific language governing permissions and
 13 * limitations under the License.
 14 */
 15
 16//
 17//  GTMHTTPFetcher.h
 18//
 19
 20// This is essentially a wrapper around NSURLConnection for POSTs and GETs.
 21// If setPostData: is called, then POST is assumed.
 22//
 23// When would you use this instead of NSURLConnection?
 24//
 25// - When you just want the result from a GET, POST, or PUT
 26// - When you want the "standard" behavior for connections (redirection handling
 27//   an so on)
 28// - When you want automatic retry on failures
 29// - When you want to avoid cookie collisions with Safari and other applications
 30// - When you are fetching resources with ETags and want to avoid the overhead
 31//   of repeated fetches of unchanged data
 32// - When you need to set a credential for the http operation
 33//
 34// This is assumed to be a one-shot fetch request; don't reuse the object
 35// for a second fetch.
 36//
 37// The fetcher may be created auto-released, in which case it will release
 38// itself after the fetch completion callback.  The fetcher is implicitly
 39// retained as long as a connection is pending.
 40//
 41// But if you may need to cancel the fetcher, retain it and have the delegate
 42// release the fetcher in the callbacks.
 43//
 44// Sample usage:
 45//
 46//  NSURLRequest *request = [NSURLRequest requestWithURL:myURL];
 47//  GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
 48//
 49//  // optional upload body data
 50//  [myFetcher setPostData:[postString dataUsingEncoding:NSUTF8StringEncoding]];
 51//
 52//  [myFetcher beginFetchWithDelegate:self
 53//                  didFinishSelector:@selector(myFetcher:finishedWithData:error:)];
 54//
 55//  Upon fetch completion, the callback selector is invoked; it should have
 56//  this signature (you can use any callback method name you want so long as
 57//  the signature matches this):
 58//
 59//  - (void)myFetcher:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)retrievedData error:(NSError *)error;
 60//
 61//  The block callback version looks like:
 62//
 63//  [myFetcher beginFetchWithCompletionHandler:^(NSData *retrievedData, NSError *error) {
 64//    if (error != nil) {
 65//      // status code or network error
 66//    } else {
 67//      // succeeded
 68//    }
 69//  }];
 70
 71//
 72// NOTE:  Fetches may retrieve data from the server even though the server
 73//        returned an error.  The failure selector is called when the server
 74//        status is >= 300, with an NSError having domain
 75//        kGTMHTTPFetcherStatusDomain and code set to the server status.
 76//
 77//        Status codes are at <http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html>
 78//
 79//
 80// Threading and queue support:
 81//
 82// Callbacks require either that the thread used to start the fetcher have a run
 83// loop spinning (typically the main thread), or that an NSOperationQueue be
 84// provided upon which the delegate callbacks will be called.  Starting with
 85// iOS 6 and Mac OS X 10.7, clients may simply create an operation queue for
 86// callbacks on a background thread:
 87//
 88//   NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
 89//   [queue setMaxConcurrentOperationCount:1];
 90//   fetcher.delegateQueue = queue;
 91//
 92// or specify the main queue for callbacks on the main thread:
 93//
 94//   fetcher.delegateQueue = [NSOperationQueue mainQueue];
 95//
 96// The client may also re-dispatch from the callbacks and notifications to
 97// a known dispatch queue:
 98//
 99//  [myFetcher beginFetchWithCompletionHandler:^(NSData *retrievedData, NSError *error) {
100//    if (error == nil) {
101//      dispatch_async(myDispatchQueue, ^{
102//        ...
103//     });
104//    }
105//  }];
106//
107//
108//
109// Downloading to disk:
110//
111// To have downloaded data saved directly to disk, specify either a path for the
112// downloadPath property, or a file handle for the downloadFileHandle property.
113// When downloading to disk, callbacks will be passed a nil for the NSData*
114// arguments.
115//
116//
117// HTTP methods and headers:
118//
119// Alternative HTTP methods, like PUT, and custom headers can be specified by
120// creating the fetcher with an appropriate NSMutableURLRequest
121//
122//
123// Proxies:
124//
125// Proxy handling is invisible so long as the system has a valid credential in
126// the keychain, which is normally true (else most NSURL-based apps would have
127// difficulty.)  But when there is a proxy authetication error, the the fetcher
128// will call the failedWithError: method with the NSURLChallenge in the error's
129// userInfo. The error method can get the challenge info like this:
130//
131//  NSURLAuthenticationChallenge *challenge
132//     = [[error userInfo] objectForKey:kGTMHTTPFetcherErrorChallengeKey];
133//  BOOL isProxyChallenge = [[challenge protectionSpace] isProxy];
134//
135// If a proxy error occurs, you can ask the user for the proxy username/password
136// and call fetcher's setProxyCredential: to provide those for the
137// next attempt to fetch.
138//
139//
140// Cookies:
141//
142// There are three supported mechanisms for remembering cookies between fetches.
143//
144// By default, GTMHTTPFetcher uses a mutable array held statically to track
145// cookies for all instantiated fetchers. This avoids server cookies being set
146// by servers for the application from interfering with Safari cookie settings,
147// and vice versa.  The fetcher cookies are lost when the application quits.
148//
149// To rely instead on WebKit's global NSHTTPCookieStorage, call
150// setCookieStorageMethod: with kGTMHTTPFetcherCookieStorageMethodSystemDefault.
151//
152// If the fetcher is created from a GTMHTTPFetcherService object
153// then the cookie storage mechanism is set to use the cookie storage in the
154// service object rather than the static storage.
155//
156//
157// Fetching for periodic checks:
158//
159// The fetcher object tracks ETag headers from responses and
160// provide an "If-None-Match" header. This allows the server to save
161// bandwidth by providing a status message instead of repeated response
162// data.
163//
164// To get this behavior, create the fetcher from an GTMHTTPFetcherService object
165// and look for a fetch callback error with code 304
166// (kGTMHTTPFetcherStatusNotModified) like this:
167//
168// - (void)myFetcher:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *)error {
169//    if ([error code] == kGTMHTTPFetcherStatusNotModified) {
170//      // |data| is empty; use the data from the previous finishedWithData: for this URL
171//    } else {
172//      // handle other server status code
173//    }
174// }
175//
176//
177// Monitoring received data
178//
179// The optional received data selector can be set with setReceivedDataSelector:
180// and should have the signature
181//
182//  - (void)myFetcher:(GTMHTTPFetcher *)fetcher receivedData:(NSData *)dataReceivedSoFar;
183//
184// The number bytes received so far is available as [fetcher downloadedLength].
185// This number may go down if a redirect causes the download to begin again from
186// a new server.
187//
188// If supplied by the server, the anticipated total download size is available
189// as [[myFetcher response] expectedContentLength] (and may be -1 for unknown
190// download sizes.)
191//
192//
193// Automatic retrying of fetches
194//
195// The fetcher can optionally create a timer and reattempt certain kinds of
196// fetch failures (status codes 408, request timeout; 503, service unavailable;
197// 504, gateway timeout; networking errors NSURLErrorTimedOut and
198// NSURLErrorNetworkConnectionLost.)  The user may set a retry selector to
199// customize the type of errors which will be retried.
200//
201// Retries are done in an exponential-backoff fashion (that is, after 1 second,
202// 2, 4, 8, and so on.)
203//
204// Enabling automatic retries looks like this:
205//  [myFetcher setRetryEnabled:YES];
206//
207// With retries enabled, the success or failure callbacks are called only
208// when no more retries will be attempted. Calling the fetcher's stopFetching
209// method will terminate the retry timer, without the finished or failure
210// selectors being invoked.
211//
212// Optionally, the client may set the maximum retry interval:
213//  [myFetcher setMaxRetryInterval:60.0]; // in seconds; default is 60 seconds
214//                                        // for downloads, 600 for uploads
215//
216// Also optionally, the client may provide a callback selector to determine
217// if a status code or other error should be retried.
218//  [myFetcher setRetrySelector:@selector(myFetcher:willRetry:forError:)];
219//
220// If set, the retry selector should have the signature:
221//   -(BOOL)fetcher:(GTMHTTPFetcher *)fetcher willRetry:(BOOL)suggestedWillRetry forError:(NSError *)error
222// and return YES to set the retry timer or NO to fail without additional
223// fetch attempts.
224//
225// The retry method may return the |suggestedWillRetry| argument to get the
226// default retry behavior.  Server status codes are present in the
227// error argument, and have the domain kGTMHTTPFetcherStatusDomain. The
228// user's method may look something like this:
229//
230//  -(BOOL)myFetcher:(GTMHTTPFetcher *)fetcher willRetry:(BOOL)suggestedWillRetry forError:(NSError *)error {
231//
232//    // perhaps examine [error domain] and [error code], or [fetcher retryCount]
233//    //
234//    // return YES to start the retry timer, NO to proceed to the failure
235//    // callback, or |suggestedWillRetry| to get default behavior for the
236//    // current error domain and code values.
237//    return suggestedWillRetry;
238//  }
239
240
241
242#pragma once
243
244#import <Foundation/Foundation.h>
245
246#if defined(GTL_TARGET_NAMESPACE)
247  // we're using target namespace macros
248  #import "GTLDefines.h"
249#elif defined(GDATA_TARGET_NAMESPACE)
250  #import "GDataDefines.h"
251#else
252  #if TARGET_OS_IPHONE
253    #ifndef GTM_FOUNDATION_ONLY
254      #define GTM_FOUNDATION_ONLY 1
255    #endif
256    #ifndef GTM_IPHONE
257      #define GTM_IPHONE 1
258    #endif
259  #endif
260#endif
261
262#if TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 40000)
263  #define GTM_BACKGROUND_FETCHING 1
264#endif
265
266#ifdef __cplusplus
267extern "C" {
268#endif
269
270// notifications
271//
272// fetch started and stopped, and fetch retry delay started and stopped
273extern NSString *const kGTMHTTPFetcherStartedNotification;
274extern NSString *const kGTMHTTPFetcherStoppedNotification;
275extern NSString *const kGTMHTTPFetcherRetryDelayStartedNotification;
276extern NSString *const kGTMHTTPFetcherRetryDelayStoppedNotification;
277
278// callback constants
279extern NSString *const kGTMHTTPFetcherErrorDomain;
280extern NSString *const kGTMHTTPFetcherStatusDomain;
281extern NSString *const kGTMHTTPFetcherErrorChallengeKey;
282extern NSString *const kGTMHTTPFetcherStatusDataKey;  // data returned with a kGTMHTTPFetcherStatusDomain error
283
284#ifdef __cplusplus
285}
286#endif
287
288enum {
289  kGTMHTTPFetcherErrorDownloadFailed = -1,
290  kGTMHTTPFetcherErrorAuthenticationChallengeFailed = -2,
291  kGTMHTTPFetcherErrorChunkUploadFailed = -3,
292  kGTMHTTPFetcherErrorFileHandleException = -4,
293  kGTMHTTPFetcherErrorBackgroundExpiration = -6,
294
295  // The code kGTMHTTPFetcherErrorAuthorizationFailed (-5) has been removed;
296  // look for status 401 instead.
297
298  kGTMHTTPFetcherStatusNotModified = 304,
299  kGTMHTTPFetcherStatusBadRequest = 400,
300  kGTMHTTPFetcherStatusUnauthorized = 401,
301  kGTMHTTPFetcherStatusForbidden = 403,
302  kGTMHTTPFetcherStatusPreconditionFailed = 412
303};
304
305// cookie storage methods
306enum {
307  kGTMHTTPFetcherCookieStorageMethodStatic = 0,
308  kGTMHTTPFetcherCookieStorageMethodFetchHistory = 1,
309  kGTMHTTPFetcherCookieStorageMethodSystemDefault = 2,
310  kGTMHTTPFetcherCookieStorageMethodNone = 3
311};
312
313#ifdef __cplusplus
314extern "C" {
315#endif
316
317void GTMAssertSelectorNilOrImplementedWithArgs(id obj, SEL sel, ...);
318
319// Utility functions for applications self-identifying to servers via a
320// user-agent header
321
322// Make a proper app name without whitespace from the given string, removing
323// whitespace and other characters that may be special parsed marks of
324// the full user-agent string.
325NSString *GTMCleanedUserAgentString(NSString *str);
326
327// Make an identifier like "MacOSX/10.7.1" or "iPod_Touch/4.1"
328NSString *GTMSystemVersionString(void);
329
330// Make a generic name and version for the current application, like
331// com.example.MyApp/1.2.3 relying on the bundle identifier and the
332// CFBundleShortVersionString or CFBundleVersion.
333//
334// The bundle ID may be overridden as the base identifier string by
335// adding to the bundle's Info.plist a "GTMUserAgentID" key.
336//
337// If no bundle ID or override is available, the process name preceded
338// by "proc_" is used.
339NSString *GTMApplicationIdentifier(NSBundle *bundle);
340
341#ifdef __cplusplus
342}  // extern "C"
343#endif
344
345@class GTMHTTPFetcher;
346
347@protocol GTMCookieStorageProtocol <NSObject>
348// This protocol allows us to call into the service without requiring
349// GTMCookieStorage sources in this project
350//
351// The public interface for cookie handling is the GTMCookieStorage class,
352// accessible from a fetcher service object's fetchHistory or from the fetcher's
353// +staticCookieStorage method.
354- (NSArray *)cookiesForURL:(NSURL *)theURL;
355- (void)setCookies:(NSArray *)newCookies;
356@end
357
358@protocol GTMHTTPFetchHistoryProtocol <NSObject>
359// This protocol allows us to call the fetch history object without requiring
360// GTMHTTPFetchHistory sources in this project
361- (void)updateRequest:(NSMutableURLRequest *)request isHTTPGet:(BOOL)isHTTPGet;
362- (BOOL)shouldCacheETaggedData;
363- (NSData *)cachedDataForRequest:(NSURLRequest *)request;
364- (id <GTMCookieStorageProtocol>)cookieStorage;
365- (void)updateFetchHistoryWithRequest:(NSURLRequest *)request
366                             response:(NSURLResponse *)response
367                       downloadedData:(NSData *)downloadedData;
368- (void)removeCachedDataForRequest:(NSURLRequest *)request;
369@end
370
371@protocol GTMHTTPFetcherServiceProtocol <NSObject>
372// This protocol allows us to call into the service without requiring
373// GTMHTTPFetcherService sources in this project
374
375@property (retain) NSOperationQueue *delegateQueue;
376
377- (BOOL)fetcherShouldBeginFetching:(GTMHTTPFetcher *)fetcher;
378- (void)fetcherDidStop:(GTMHTTPFetcher *)fetcher;
379
380- (GTMHTTPFetcher *)fetcherWithRequest:(NSURLRequest *)request;
381- (BOOL)isDelayingFetcher:(GTMHTTPFetcher *)fetcher;
382@end
383
384@protocol GTMFetcherAuthorizationProtocol <NSObject>
385@required
386// This protocol allows us to call the authorizer without requiring its sources
387// in this project.
388- (void)authorizeRequest:(NSMutableURLRequest *)request
389                delegate:(id)delegate
390       didFinishSelector:(SEL)sel;
391
392- (void)stopAuthorization;
393
394- (void)stopAuthorizationForRequest:(NSURLRequest *)request;
395
396- (BOOL)isAuthorizingRequest:(NSURLRequest *)request;
397
398- (BOOL)isAuthorizedRequest:(NSURLRequest *)request;
399
400@property (retain, readonly) NSString *userEmail;
401
402@optional
403
404// Indicate if authorization may be attempted. Even if this succeeds,
405// authorization may fail if the user's permissions have been revoked.
406@property (readonly) BOOL canAuthorize;
407
408// For development only, allow authorization of non-SSL requests, allowing
409// transmission of the bearer token unencrypted.
410@property (assign) BOOL shouldAuthorizeAllRequests;
411
412#if NS_BLOCKS_AVAILABLE
413- (void)authorizeRequest:(NSMutableURLRequest *)request
414       completionHandler:(void (^)(NSError *error))handler;
415#endif
416
417@property (assign) id <GTMHTTPFetcherServiceProtocol> fetcherService; // WEAK
418
419- (BOOL)primeForRefresh;
420
421@end
422
423// GTMHTTPFetcher objects are used for async retrieval of an http get or post
424//
425// See additional comments at the beginning of this file
426@interface GTMHTTPFetcher : NSObject {
427 @protected
428  NSMutableURLRequest *request_;
429  NSURLConnection *connection_;
430  NSMutableData *downloadedData_;
431  NSString *downloadPath_;
432  NSString *temporaryDownloadPath_;
433  NSFileHandle *downloadFileHandle_;
434  unsigned long long downloadedLength_;
435  NSURLCredential *credential_;     // username & password
436  NSURLCredential *proxyCredential_; // credential supplied to proxy servers
437  NSData *postData_;
438  NSInputStream *postStream_;
439  NSMutableData *loggedStreamData_;
440  NSURLResponse *response_;         // set in connection:didReceiveResponse:
441  id delegate_;
442  SEL finishedSel_;                 // should by implemented by delegate
443  SEL sentDataSel_;                 // optional, set with setSentDataSelector
444  SEL receivedDataSel_;             // optional, set with setReceivedDataSelector
445#if NS_BLOCKS_AVAILABLE
446  void (^completionBlock_)(NSData *, NSError *);
447  void (^receivedDataBlock_)(NSData *);
448  void (^sentDataBlock_)(NSInteger, NSInteger, NSInteger);
449  BOOL (^retryBlock_)(BOOL, NSError *);
450#elif !__LP64__
451  // placeholders: for 32-bit builds, keep the size of the object's ivar section
452  // the same with and without blocks
453  id completionPlaceholder_;
454  id receivedDataPlaceholder_;
455  id sentDataPlaceholder_;
456  id retryPlaceholder_;
457#endif
458  BOOL hasConnectionEnded_;         // set if the connection need not be cancelled
459  BOOL isCancellingChallenge_;      // set only when cancelling an auth challenge
460  BOOL isStopNotificationNeeded_;   // set when start notification has been sent
461  BOOL shouldFetchInBackground_;
462#if GTM_BACKGROUND_FETCHING
463  NSUInteger backgroundTaskIdentifer_; // UIBackgroundTaskIdentifier
464#endif
465  id userData_;                     // retained, if set by caller
466  NSMutableDictionary *properties_; // more data retained for caller
467  NSArray *runLoopModes_;           // optional
468  NSOperationQueue *delegateQueue_; // optional; available iOS 6/10.7 and later
469  id <GTMHTTPFetchHistoryProtocol> fetchHistory_; // if supplied by the caller, used for Last-Modified-Since checks and cookies
470  NSInteger cookieStorageMethod_;   // constant from above
471  id <GTMCookieStorageProtocol> cookieStorage_;
472
473  id <GTMFetcherAuthorizationProtocol> authorizer_;
474
475  // the service object that created and monitors this fetcher, if any
476  id <GTMHTTPFetcherServiceProtocol> service_;
477  NSString *serviceHost_;
478  NSInteger servicePriority_;
479  NSThread *thread_;
480
481  BOOL isRetryEnabled_;             // user wants auto-retry
482  SEL retrySel_;                    // optional; set with setRetrySelector
483  NSTimer *retryTimer_;
484  NSUInteger retryCount_;
485  NSTimeInterval maxRetryInterval_; // default 600 seconds
486  NSTimeInterval minRetryInterval_; // random between 1 and 2 seconds
487  NSTimeInterval retryFactor_;      // default interval multiplier is 2
488  NSTimeInterval lastRetryInterval_;
489  NSDate *initialRequestDate_;
490  BOOL hasAttemptedAuthRefresh_;
491
492  NSString *comment_;               // comment for log
493  NSString *log_;
494#if !STRIP_GTM_FETCH_LOGGING
495  NSURL *redirectedFromURL_;
496  NSString *logRequestBody_;
497  NSString *logResponseBody_;
498  BOOL hasLoggedError_;
499  BOOL shouldDeferResponseBodyLogging_;
500#endif
501}
502
503// Create a fetcher
504//
505// fetcherWithRequest will return an autoreleased fetcher, but if
506// the connection is successfully created, the connection should retain the
507// fetcher for the life of the connection as well. So the caller doesn't have
508// to retain the fetcher explicitly unless they want to be able to cancel it.
509+ (GTMHTTPFetcher *)fetcherWithRequest:(NSURLRequest *)request;
510
511// Convenience methods that make a request, like +fetcherWithRequest
512+ (GTMHTTPFetcher *)fetcherWithURL:(NSURL *)requestURL;
513+ (GTMHTTPFetcher *)fetcherWithURLString:(NSString *)requestURLString;
514
515// Designated initializer
516- (id)initWithRequest:(NSURLRequest *)request;
517
518// Fetcher request
519//
520// The underlying request is mutable and may be modified by the caller
521@property (retain) NSMutableURLRequest *mutableRequest;
522
523// Setting the credential is optional; it is used if the connection receives
524// an authentication challenge
525@property (retain) NSURLCredential *credential;
526
527// Setting the proxy credential is optional; it is used if the connection
528// receives an authentication challenge from a proxy
529@property (retain) NSURLCredential *proxyCredential;
530
531// If post data or stream is not set, then a GET retrieval method is assumed
532@property (retain) NSData *postData;
533@property (retain) NSInputStream *postStream;
534
535// The default cookie storage method is kGTMHTTPFetcherCookieStorageMethodStatic
536// without a fetch history set, and kGTMHTTPFetcherCookieStorageMethodFetchHistory
537// with a fetch history set
538//
539// Applications needing control of cookies across a sequence of fetches should
540// create fetchers from a GTMHTTPFetcherService object (which encapsulates
541// fetch history) for a well-defined cookie store
542@property (assign) NSInteger cookieStorageMethod;
543
544+ (id <GTMCookieStorageProtocol>)staticCookieStorage;
545
546// Object to add authorization to the request, if needed
547@property (retain) id <GTMFetcherAuthorizationProtocol> authorizer;
548
549// The service object that created and monitors this fetcher, if any
550@property (retain) id <GTMHTTPFetcherServiceProtocol> service;
551
552// The host, if any, used to classify this fetcher in the fetcher service
553@property (copy) NSString *serviceHost;
554
555// The priority, if any, used for starting fetchers in the fetcher service
556//
557// Lower values are higher priority; the default is 0, and values may
558// be negative or positive. This priority affects only the start order of
559// fetchers that are being delayed by a fetcher service.
560@property (assign) NSInteger servicePriority;
561
562// The thread used to run this fetcher in the fetcher service when no operation
563// queue is provided.
564@property (retain) NSThread *thread;
565
566// The delegate is retained during the connection
567@property (retain) id delegate;
568
569// On iOS 4 and later, the fetch may optionally continue while the app is in the
570// background until finished or stopped by OS expiration
571//
572// The default value is NO
573//
574// For Mac OS X, background fetches are always supported, and this property
575// is ignored
576@property (assign) BOOL shouldFetchInBackground;
577
578// The delegate's optional sentData selector may be used to monitor upload
579// progress. It should have a signature like:
580//  - (void)myFetcher:(GTMHTTPFetcher *)fetcher
581//              didSendBytes:(NSInteger)bytesSent
582//            totalBytesSent:(NSInteger)totalBytesSent
583//  totalBytesExpectedToSend:(NSInteger)totalBytesExpectedToSend;
584//
585// +doesSupportSentDataCallback indicates if this delegate method is supported
586+ (BOOL)doesSupportSentDataCallback;
587
588@property (assign) SEL sentDataSelector;
589
590// The delegate's optional receivedData selector may be used to monitor download
591// progress. It should have a signature like:
592//  - (void)myFetcher:(GTMHTTPFetcher *)fetcher
593//       receivedData:(NSData *)dataReceivedSoFar;
594//
595// The dataReceived argument will be nil when downloading to a path or to a
596// file handle.
597//
598// Applications should not use this method to accumulate the received data;
599// the callback method or block supplied to the beginFetch call will have
600// the complete NSData received.
601@property (assign) SEL receivedDataSelector;
602
603#if NS_BLOCKS_AVAILABLE
604// The full interface to the block is provided rather than just a typedef for
605// its parameter list in order to get more useful code completion in the Xcode
606// editor
607@property (copy) void (^sentDataBlock)(NSInteger bytesSent, NSInteger totalBytesSent, NSInteger bytesExpectedToSend);
608
609// The dataReceived argument will be nil when downloading to a path or to
610// a file handle
611@property (copy) void (^receivedDataBlock)(NSData *dataReceivedSoFar);
612#endif
613
614// retrying; see comments at the top of the file.  Calling
615// setRetryEnabled(YES) resets the min and max retry intervals.
616@property (assign, getter=isRetryEnabled) BOOL retryEnabled;
617
618// Retry selector or block is optional for retries.
619//
620// If present, it should have the signature:
621//   -(BOOL)fetcher:(GTMHTTPFetcher *)fetcher willRetry:(BOOL)suggestedWillRetry forError:(NSError *)error
622// and return YES to cause a retry.  See comments at the top of this file.
623@property (assign) SEL retrySelector;
624
625#if NS_BLOCKS_AVAILABLE
626@property (copy) BOOL (^retryBlock)(BOOL suggestedWillRetry, NSError *error);
627#endif
628
629// Retry intervals must be strictly less than maxRetryInterval, else
630// they will be limited to maxRetryInterval and no further retries will
631// be attempted.  Setting maxRetryInterval to 0.0 will reset it to the
632// default value, 600 seconds.
633
634@property (assign) NSTimeInterval maxRetryInterval;
635
636// Starting retry interval.  Setting minRetryInterval to 0.0 will reset it
637// to a random value between 1.0 and 2.0 seconds.  Clients should normally not
638// call this except for unit testing.
639@property (assign) NSTimeInterval minRetryInterval;
640
641// Multiplier used to increase the interval between retries, typically 2.0.
642// Clients should not need to call this.
643@property (assign) double retryFactor;
644
645// Number of retries attempted
646@property (readonly) NSUInteger retryCount;
647
648// interval delay to precede next retry
649@property (readonly) NSTimeInterval nextRetryInterval;
650
651// Begin fetching the request
652//
653// The delegate can optionally implement the finished selectors or pass NULL
654// for it.
655//
656// Returns YES if the fetch is initiated.  The delegate is retained between
657// the beginFetch call until after the finish callback.
658//
659// An error is passed to the callback for server statuses 300 or
660// higher, with the status stored as the error object's code.
661//
662// finishedSEL has a signature like:
663//   - (void)fetcher:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *)error;
664//
665// If the application has specified a downloadPath or downloadFileHandle
666// for the fetcher, the data parameter passed to the callback will be nil.
667
668- (BOOL)beginFetchWithDelegate:(id)delegate
669             didFinishSelector:(SEL)finishedSEL;
670
671#if NS_BLOCKS_AVAILABLE
672- (BOOL)beginFetchWithCompletionHandler:(void (^)(NSData *data, NSError *error))handler;
673#endif
674
675
676// Returns YES if this is in the process of fetching a URL
677- (BOOL)isFetching;
678
679// Cancel the fetch of the request that's currently in progress
680- (void)stopFetching;
681
682// Return the status code from the server response
683@property (readonly) NSInteger statusCode;
684
685// Return the http headers from the response
686@property (retain, readonly) NSDictionary *responseHeaders;
687
688// The response, once it's been received
689@property (retain) NSURLResponse *response;
690
691// Bytes downloaded so far
692@property (readonly) unsigned long long downloadedLength;
693
694// Buffer of currently-downloaded data
695@property (readonly, retain) NSData *downloadedData;
696
697// Path in which to non-atomically create a file for storing the downloaded data
698//
699// The path must be set before fetching begins.  The download file handle
700// will be created for the path, and can be used to monitor progress. If a file
701// already exists at the path, it will be overwritten.
702@property (copy) NSString *downloadPath;
703
704// If downloadFileHandle is set, data received is immediately appended to
705// the file handle rather than being accumulated in the downloadedData property
706//
707// The file handle supplied must allow writing and support seekToFileOffset:,
708// and must be set before fetching begins.  Setting a download path will
709// override the file handle property.
710@property (retain) NSFileHandle *downloadFileHandle;
711
712// The optional fetchHistory object is used for a sequence of fetchers to
713// remember ETags, cache ETagged data, and store cookies.  Typically, this
714// is set by a GTMFetcherService object when it creates a fetcher.
715//
716// Side effect: setting fetch history implicitly calls setCookieStorageMethod:
717@property (retain) id <GTMHTTPFetchHistoryProtocol> fetchHistory;
718
719// userData is retained for the convenience of the caller
720@property (retain) id userData;
721
722// Stored property values are retained for the convenience of the caller
723@property (copy) NSMutableDictionary *properties;
724
725- (void)setProperty:(id)obj forKey:(NSString *)key; // pass nil obj to remove property
726- (id)propertyForKey:(NSString *)key;
727
728- (void)addPropertiesFromDictionary:(NSDictionary *)dict;
729
730// Comments are useful for logging
731@property (copy) NSString *comment;
732
733- (void)setCommentWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2);
734
735// Log of request and response, if logging is enabled
736@property (copy) NSString *log;
737
738// Callbacks can be invoked on an operation queue rather than via the run loop,
739// starting on 10.7 and iOS 6.  If a delegate queue is supplied. the run loop
740// modes are ignored.
741@property (retain) NSOperationQueue *delegateQueue;
742
743// Using the fetcher while a modal dialog is displayed requires setting the
744// run-loop modes to include NSModalPanelRunLoopMode
745@property (retain) NSArray *runLoopModes;
746
747// Users who wish to replace GTMHTTPFetcher's use of NSURLConnection
748// can do so globally here.  The replacement should be a subclass of
749// NSURLConnection.
750+ (Class)connectionClass;
751+ (void)setConnectionClass:(Class)theClass;
752
753// Spin the run loop, discarding events, until the fetch has completed
754//
755// This is only for use in testing or in tools without a user interface.
756//
757// Synchronous fetches should never be done by shipping apps; they are
758// sufficient reason for rejection from the app store.
759- (void)waitForCompletionWithTimeout:(NSTimeInterval)timeoutInSeconds;
760
761#if STRIP_GTM_FETCH_LOGGING
762// if logging is stripped, provide a stub for the main method
763// for controlling logging
764+ (void)setLoggingEnabled:(BOOL)flag;
765#endif // STRIP_GTM_FETCH_LOGGING
766
767@end