BBGMultiAccountManager
 All Classes Files Functions Variables Enumerator Properties Defines
GMultiAccountManager/GMultiAccountManager/GTMHTTPFetcher.h
Go to the documentation of this file.
00001 /* Copyright (c) 2011 Google Inc.
00002  *
00003  * Licensed under the Apache License, Version 2.0 (the "License");
00004  * you may not use this file except in compliance with the License.
00005  * You may obtain a copy of the License at
00006  *
00007  *     http://www.apache.org/licenses/LICENSE-2.0
00008  *
00009  * Unless required by applicable law or agreed to in writing, software
00010  * distributed under the License is distributed on an "AS IS" BASIS,
00011  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012  * See the License for the specific language governing permissions and
00013  * limitations under the License.
00014  */
00015 
00016 //
00017 //  GTMHTTPFetcher.h
00018 //
00019 
00020 // This is essentially a wrapper around NSURLConnection for POSTs and GETs.
00021 // If setPostData: is called, then POST is assumed.
00022 //
00023 // When would you use this instead of NSURLConnection?
00024 //
00025 // - When you just want the result from a GET, POST, or PUT
00026 // - When you want the "standard" behavior for connections (redirection handling
00027 //   an so on)
00028 // - When you want automatic retry on failures
00029 // - When you want to avoid cookie collisions with Safari and other applications
00030 // - When you are fetching resources with ETags and want to avoid the overhead
00031 //   of repeated fetches of unchanged data
00032 // - When you need to set a credential for the http operation
00033 //
00034 // This is assumed to be a one-shot fetch request; don't reuse the object
00035 // for a second fetch.
00036 //
00037 // The fetcher may be created auto-released, in which case it will release
00038 // itself after the fetch completion callback.  The fetcher is implicitly
00039 // retained as long as a connection is pending.
00040 //
00041 // But if you may need to cancel the fetcher, retain it and have the delegate
00042 // release the fetcher in the callbacks.
00043 //
00044 // Sample usage:
00045 //
00046 //  NSURLRequest *request = [NSURLRequest requestWithURL:myURL];
00047 //  GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
00048 //
00049 //  // optional upload body data
00050 //  [myFetcher setPostData:[postString dataUsingEncoding:NSUTF8StringEncoding]];
00051 //
00052 //  [myFetcher beginFetchWithDelegate:self
00053 //                  didFinishSelector:@selector(myFetcher:finishedWithData:error:)];
00054 //
00055 //  Upon fetch completion, the callback selector is invoked; it should have
00056 //  this signature (you can use any callback method name you want so long as
00057 //  the signature matches this):
00058 //
00059 //  - (void)myFetcher:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)retrievedData error:(NSError *)error;
00060 //
00061 //  The block callback version looks like:
00062 //
00063 //  [myFetcher beginFetchWithCompletionHandler:^(NSData *retrievedData, NSError *error) {
00064 //    if (error != nil) {
00065 //      // status code or network error
00066 //    } else {
00067 //      // succeeded
00068 //    }
00069 //  }];
00070 
00071 //
00072 // NOTE:  Fetches may retrieve data from the server even though the server
00073 //        returned an error.  The failure selector is called when the server
00074 //        status is >= 300, with an NSError having domain
00075 //        kGTMHTTPFetcherStatusDomain and code set to the server status.
00076 //
00077 //        Status codes are at <http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html>
00078 //
00079 //
00080 // Downloading to disk:
00081 //
00082 // To have downloaded data saved directly to disk, specify either a path for the
00083 // downloadPath property, or a file handle for the downloadFileHandle property.
00084 // When downloading to disk, callbacks will be passed a nil for the NSData*
00085 // arguments.
00086 //
00087 //
00088 // HTTP methods and headers:
00089 //
00090 // Alternative HTTP methods, like PUT, and custom headers can be specified by
00091 // creating the fetcher with an appropriate NSMutableURLRequest
00092 //
00093 //
00094 // Proxies:
00095 //
00096 // Proxy handling is invisible so long as the system has a valid credential in
00097 // the keychain, which is normally true (else most NSURL-based apps would have
00098 // difficulty.)  But when there is a proxy authetication error, the the fetcher
00099 // will call the failedWithError: method with the NSURLChallenge in the error's
00100 // userInfo. The error method can get the challenge info like this:
00101 //
00102 //  NSURLAuthenticationChallenge *challenge
00103 //     = [[error userInfo] objectForKey:kGTMHTTPFetcherErrorChallengeKey];
00104 //  BOOL isProxyChallenge = [[challenge protectionSpace] isProxy];
00105 //
00106 // If a proxy error occurs, you can ask the user for the proxy username/password
00107 // and call fetcher's setProxyCredential: to provide those for the
00108 // next attempt to fetch.
00109 //
00110 //
00111 // Cookies:
00112 //
00113 // There are three supported mechanisms for remembering cookies between fetches.
00114 //
00115 // By default, GTMHTTPFetcher uses a mutable array held statically to track
00116 // cookies for all instantiated fetchers. This avoids server cookies being set
00117 // by servers for the application from interfering with Safari cookie settings,
00118 // and vice versa.  The fetcher cookies are lost when the application quits.
00119 //
00120 // To rely instead on WebKit's global NSHTTPCookieStorage, call
00121 // setCookieStorageMethod: with kGTMHTTPFetcherCookieStorageMethodSystemDefault.
00122 //
00123 // If the fetcher is created from a GTMHTTPFetcherService object
00124 // then the cookie storage mechanism is set to use the cookie storage in the
00125 // service object rather than the static storage.
00126 //
00127 //
00128 // Fetching for periodic checks:
00129 //
00130 // The fetcher object tracks ETag headers from responses and
00131 // provide an "If-None-Match" header. This allows the server to save
00132 // bandwidth by providing a status message instead of repeated response
00133 // data.
00134 //
00135 // To get this behavior, create the fetcher from an GTMHTTPFetcherService object
00136 // and look for a fetch callback error with code 304
00137 // (kGTMHTTPFetcherStatusNotModified) like this:
00138 //
00139 // - (void)myFetcher:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *)error {
00140 //    if ([error code] == kGTMHTTPFetcherStatusNotModified) {
00141 //      // |data| is empty; use the data from the previous finishedWithData: for this URL
00142 //    } else {
00143 //      // handle other server status code
00144 //    }
00145 // }
00146 //
00147 //
00148 // Monitoring received data
00149 //
00150 // The optional received data selector can be set with setReceivedDataSelector:
00151 // and should have the signature
00152 //
00153 //  - (void)myFetcher:(GTMHTTPFetcher *)fetcher receivedData:(NSData *)dataReceivedSoFar;
00154 //
00155 // The number bytes received so far is available as [fetcher downloadedLength].
00156 // This number may go down if a redirect causes the download to begin again from
00157 // a new server.
00158 //
00159 // If supplied by the server, the anticipated total download size is available
00160 // as [[myFetcher response] expectedContentLength] (and may be -1 for unknown
00161 // download sizes.)
00162 //
00163 //
00164 // Automatic retrying of fetches
00165 //
00166 // The fetcher can optionally create a timer and reattempt certain kinds of
00167 // fetch failures (status codes 408, request timeout; 503, service unavailable;
00168 // 504, gateway timeout; networking errors NSURLErrorTimedOut and
00169 // NSURLErrorNetworkConnectionLost.)  The user may set a retry selector to
00170 // customize the type of errors which will be retried.
00171 //
00172 // Retries are done in an exponential-backoff fashion (that is, after 1 second,
00173 // 2, 4, 8, and so on.)
00174 //
00175 // Enabling automatic retries looks like this:
00176 //  [myFetcher setRetryEnabled:YES];
00177 //
00178 // With retries enabled, the success or failure callbacks are called only
00179 // when no more retries will be attempted. Calling the fetcher's stopFetching
00180 // method will terminate the retry timer, without the finished or failure
00181 // selectors being invoked.
00182 //
00183 // Optionally, the client may set the maximum retry interval:
00184 //  [myFetcher setMaxRetryInterval:60.0]; // in seconds; default is 60 seconds
00185 //                                        // for downloads, 600 for uploads
00186 //
00187 // Also optionally, the client may provide a callback selector to determine
00188 // if a status code or other error should be retried.
00189 //  [myFetcher setRetrySelector:@selector(myFetcher:willRetry:forError:)];
00190 //
00191 // If set, the retry selector should have the signature:
00192 //   -(BOOL)fetcher:(GTMHTTPFetcher *)fetcher willRetry:(BOOL)suggestedWillRetry forError:(NSError *)error
00193 // and return YES to set the retry timer or NO to fail without additional
00194 // fetch attempts.
00195 //
00196 // The retry method may return the |suggestedWillRetry| argument to get the
00197 // default retry behavior.  Server status codes are present in the
00198 // error argument, and have the domain kGTMHTTPFetcherStatusDomain. The
00199 // user's method may look something like this:
00200 //
00201 //  -(BOOL)myFetcher:(GTMHTTPFetcher *)fetcher willRetry:(BOOL)suggestedWillRetry forError:(NSError *)error {
00202 //
00203 //    // perhaps examine [error domain] and [error code], or [fetcher retryCount]
00204 //    //
00205 //    // return YES to start the retry timer, NO to proceed to the failure
00206 //    // callback, or |suggestedWillRetry| to get default behavior for the
00207 //    // current error domain and code values.
00208 //    return suggestedWillRetry;
00209 //  }
00210 
00211 
00212 
00213 #pragma once
00214 
00215 #import <Foundation/Foundation.h>
00216 
00217 #if defined(GTL_TARGET_NAMESPACE)
00218   // we're using target namespace macros
00219   #import "GTLDefines.h"
00220 #elif defined(GDATA_TARGET_NAMESPACE)
00221   #import "GDataDefines.h"
00222 #else
00223   #if TARGET_OS_IPHONE
00224     #ifndef GTM_FOUNDATION_ONLY
00225       #define GTM_FOUNDATION_ONLY 1
00226     #endif
00227     #ifndef GTM_IPHONE
00228       #define GTM_IPHONE 1
00229     #endif
00230   #endif
00231 #endif
00232 
00233 #if TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 40000)
00234   #define GTM_BACKGROUND_FETCHING 1
00235 #endif
00236 
00237 #undef _EXTERN
00238 #undef _INITIALIZE_AS
00239 #ifdef GTMHTTPFETCHER_DEFINE_GLOBALS
00240   #define _EXTERN
00241   #define _INITIALIZE_AS(x) =x
00242 #else
00243   #if defined(__cplusplus)
00244     #define _EXTERN extern "C"
00245   #else
00246     #define _EXTERN extern
00247   #endif
00248   #define _INITIALIZE_AS(x)
00249 #endif
00250 
00251 // notifications
00252 //
00253 // fetch started and stopped, and fetch retry delay started and stopped
00254 _EXTERN NSString* const kGTMHTTPFetcherStartedNotification           _INITIALIZE_AS(@"kGTMHTTPFetcherStartedNotification");
00255 _EXTERN NSString* const kGTMHTTPFetcherStoppedNotification           _INITIALIZE_AS(@"kGTMHTTPFetcherStoppedNotification");
00256 _EXTERN NSString* const kGTMHTTPFetcherRetryDelayStartedNotification _INITIALIZE_AS(@"kGTMHTTPFetcherRetryDelayStartedNotification");
00257 _EXTERN NSString* const kGTMHTTPFetcherRetryDelayStoppedNotification _INITIALIZE_AS(@"kGTMHTTPFetcherRetryDelayStoppedNotification");
00258 
00259 // callback constants
00260 _EXTERN NSString* const kGTMHTTPFetcherErrorDomain       _INITIALIZE_AS(@"com.google.GTMHTTPFetcher");
00261 _EXTERN NSString* const kGTMHTTPFetcherStatusDomain      _INITIALIZE_AS(@"com.google.HTTPStatus");
00262 _EXTERN NSString* const kGTMHTTPFetcherErrorChallengeKey _INITIALIZE_AS(@"challenge");
00263 _EXTERN NSString* const kGTMHTTPFetcherStatusDataKey     _INITIALIZE_AS(@"data");  // data returned with a kGTMHTTPFetcherStatusDomain error
00264 
00265 enum {
00266   kGTMHTTPFetcherErrorDownloadFailed = -1,
00267   kGTMHTTPFetcherErrorAuthenticationChallengeFailed = -2,
00268   kGTMHTTPFetcherErrorChunkUploadFailed = -3,
00269   kGTMHTTPFetcherErrorFileHandleException = -4,
00270   kGTMHTTPFetcherErrorBackgroundExpiration = -6,
00271 
00272   // The code kGTMHTTPFetcherErrorAuthorizationFailed (-5) has been removed;
00273   // look for status 401 instead.
00274 
00275   kGTMHTTPFetcherStatusNotModified = 304,
00276   kGTMHTTPFetcherStatusBadRequest = 400,
00277   kGTMHTTPFetcherStatusUnauthorized = 401,
00278   kGTMHTTPFetcherStatusForbidden = 403,
00279   kGTMHTTPFetcherStatusPreconditionFailed = 412
00280 };
00281 
00282 // cookie storage methods
00283 enum {
00284   kGTMHTTPFetcherCookieStorageMethodStatic = 0,
00285   kGTMHTTPFetcherCookieStorageMethodFetchHistory = 1,
00286   kGTMHTTPFetcherCookieStorageMethodSystemDefault = 2,
00287   kGTMHTTPFetcherCookieStorageMethodNone = 3
00288 };
00289 
00290 void GTMAssertSelectorNilOrImplementedWithArgs(id obj, SEL sel, ...);
00291 
00292 // Utility functions for applications self-identifying to servers via a
00293 // user-agent header
00294 
00295 // Make a proper app name without whitespace from the given string, removing
00296 // whitespace and other characters that may be special parsed marks of
00297 // the full user-agent string.
00298 NSString *GTMCleanedUserAgentString(NSString *str);
00299 
00300 // Make an identifier like "MacOSX/10.7.1" or "iPod_Touch/4.1"
00301 NSString *GTMSystemVersionString(void);
00302 
00303 // Make a generic name and version for the current application, like
00304 // com.example.MyApp/1.2.3 relying on the bundle identifier and the
00305 // CFBundleShortVersionString or CFBundleVersion.  If no bundle ID
00306 // is available, the process name preceded by "proc_" is used.
00307 NSString *GTMApplicationIdentifier(NSBundle *bundle);
00308 
00309 @class GTMHTTPFetcher;
00310 
00311 @protocol GTMCookieStorageProtocol <NSObject>
00312 // This protocol allows us to call into the service without requiring
00313 // GTMCookieStorage sources in this project
00314 //
00315 // The public interface for cookie handling is the GTMCookieStorage class,
00316 // accessible from a fetcher service object's fetchHistory or from the fetcher's
00317 // +staticCookieStorage method.
00318 - (NSArray *)cookiesForURL:(NSURL *)theURL;
00319 - (void)setCookies:(NSArray *)newCookies;
00320 @end
00321 
00322 @protocol GTMHTTPFetchHistoryProtocol <NSObject>
00323 // This protocol allows us to call the fetch history object without requiring
00324 // GTMHTTPFetchHistory sources in this project
00325 - (void)updateRequest:(NSMutableURLRequest *)request isHTTPGet:(BOOL)isHTTPGet;
00326 - (BOOL)shouldCacheETaggedData;
00327 - (NSData *)cachedDataForRequest:(NSURLRequest *)request;
00328 - (id <GTMCookieStorageProtocol>)cookieStorage;
00329 - (void)updateFetchHistoryWithRequest:(NSURLRequest *)request
00330                              response:(NSURLResponse *)response
00331                        downloadedData:(NSData *)downloadedData;
00332 - (void)removeCachedDataForRequest:(NSURLRequest *)request;
00333 @end
00334 
00335 @protocol GTMHTTPFetcherServiceProtocol <NSObject>
00336 // This protocol allows us to call into the service without requiring
00337 // GTMHTTPFetcherService sources in this project
00338 - (BOOL)fetcherShouldBeginFetching:(GTMHTTPFetcher *)fetcher;
00339 - (void)fetcherDidStop:(GTMHTTPFetcher *)fetcher;
00340 
00341 - (GTMHTTPFetcher *)fetcherWithRequest:(NSURLRequest *)request;
00342 - (BOOL)isDelayingFetcher:(GTMHTTPFetcher *)fetcher;
00343 @end
00344 
00345 @protocol GTMFetcherAuthorizationProtocol <NSObject>
00346 @required
00347 // This protocol allows us to call the authorizer without requiring its sources
00348 // in this project
00349 - (void)authorizeRequest:(NSMutableURLRequest *)request
00350                 delegate:(id)delegate
00351        didFinishSelector:(SEL)sel;
00352 
00353 - (void)stopAuthorization;
00354 
00355 - (BOOL)isAuthorizingRequest:(NSURLRequest *)request;
00356 
00357 - (BOOL)isAuthorizedRequest:(NSURLRequest *)request;
00358 
00359 - (NSString *)userEmail;
00360 
00361 @optional
00362 @property (assign) id <GTMHTTPFetcherServiceProtocol> fetcherService; // WEAK
00363 
00364 - (BOOL)primeForRefresh;
00365 @end
00366 
00367 // GTMHTTPFetcher objects are used for async retrieval of an http get or post
00368 //
00369 // See additional comments at the beginning of this file
00370 @interface GTMHTTPFetcher : NSObject {
00371  @protected
00372   NSMutableURLRequest *request_;
00373   NSURLConnection *connection_;
00374   NSMutableData *downloadedData_;
00375   NSString *downloadPath_;
00376   NSString *temporaryDownloadPath_;
00377   NSFileHandle *downloadFileHandle_;
00378   unsigned long long downloadedLength_;
00379   NSURLCredential *credential_;     // username & password
00380   NSURLCredential *proxyCredential_; // credential supplied to proxy servers
00381   NSData *postData_;
00382   NSInputStream *postStream_;
00383   NSMutableData *loggedStreamData_;
00384   NSURLResponse *response_;         // set in connection:didReceiveResponse:
00385   id delegate_;
00386   SEL finishedSel_;                 // should by implemented by delegate
00387   SEL sentDataSel_;                 // optional, set with setSentDataSelector
00388   SEL receivedDataSel_;             // optional, set with setReceivedDataSelector
00389 #if NS_BLOCKS_AVAILABLE
00390   void (^completionBlock_)(NSData *, NSError *);
00391   void (^receivedDataBlock_)(NSData *);
00392   void (^sentDataBlock_)(NSInteger, NSInteger, NSInteger);
00393   BOOL (^retryBlock_)(BOOL, NSError *);
00394 #elif !__LP64__
00395   // placeholders: for 32-bit builds, keep the size of the object's ivar section
00396   // the same with and without blocks
00397   id completionPlaceholder_;
00398   id receivedDataPlaceholder_;
00399   id sentDataPlaceholder_;
00400   id retryPlaceholder_;
00401 #endif
00402   BOOL hasConnectionEnded_;         // set if the connection need not be cancelled
00403   BOOL isCancellingChallenge_;      // set only when cancelling an auth challenge
00404   BOOL isStopNotificationNeeded_;   // set when start notification has been sent
00405   BOOL shouldFetchInBackground_;
00406 #if GTM_BACKGROUND_FETCHING
00407   NSUInteger backgroundTaskIdentifer_; // UIBackgroundTaskIdentifier
00408 #endif
00409   id userData_;                     // retained, if set by caller
00410   NSMutableDictionary *properties_; // more data retained for caller
00411   NSArray *runLoopModes_;           // optional, for 10.5 and later
00412   id <GTMHTTPFetchHistoryProtocol> fetchHistory_; // if supplied by the caller, used for Last-Modified-Since checks and cookies
00413   NSInteger cookieStorageMethod_;   // constant from above
00414   id <GTMCookieStorageProtocol> cookieStorage_;
00415   
00416   id <GTMFetcherAuthorizationProtocol> authorizer_;
00417 
00418   // the service object that created and monitors this fetcher, if any
00419   id <GTMHTTPFetcherServiceProtocol> service_;
00420   NSString *serviceHost_;
00421   NSInteger servicePriority_;
00422   NSThread *thread_;
00423 
00424   BOOL isRetryEnabled_;             // user wants auto-retry
00425   SEL retrySel_;                    // optional; set with setRetrySelector
00426   NSTimer *retryTimer_;
00427   NSUInteger retryCount_;
00428   NSTimeInterval maxRetryInterval_; // default 600 seconds
00429   NSTimeInterval minRetryInterval_; // random between 1 and 2 seconds
00430   NSTimeInterval retryFactor_;      // default interval multiplier is 2
00431   NSTimeInterval lastRetryInterval_;
00432   BOOL hasAttemptedAuthRefresh_;
00433 
00434   NSString *comment_;               // comment for log
00435   NSString *log_;
00436 }
00437 
00438 // Create a fetcher
00439 //
00440 // fetcherWithRequest will return an autoreleased fetcher, but if
00441 // the connection is successfully created, the connection should retain the
00442 // fetcher for the life of the connection as well. So the caller doesn't have
00443 // to retain the fetcher explicitly unless they want to be able to cancel it.
00444 + (GTMHTTPFetcher *)fetcherWithRequest:(NSURLRequest *)request;
00445 
00446 // Convenience methods that make a request, like +fetcherWithRequest
00447 + (GTMHTTPFetcher *)fetcherWithURL:(NSURL *)requestURL;
00448 + (GTMHTTPFetcher *)fetcherWithURLString:(NSString *)requestURLString;
00449 
00450 // Designated initializer
00451 - (id)initWithRequest:(NSURLRequest *)request;
00452 
00453 // Fetcher request
00454 //
00455 // The underlying request is mutable and may be modified by the caller
00456 @property (retain) NSMutableURLRequest *mutableRequest;
00457 
00458 // Setting the credential is optional; it is used if the connection receives
00459 // an authentication challenge
00460 @property (retain) NSURLCredential *credential;
00461 
00462 // Setting the proxy credential is optional; it is used if the connection
00463 // receives an authentication challenge from a proxy
00464 @property (retain) NSURLCredential *proxyCredential;
00465 
00466 // If post data or stream is not set, then a GET retrieval method is assumed
00467 @property (retain) NSData *postData;
00468 @property (retain) NSInputStream *postStream;
00469 
00470 // The default cookie storage method is kGTMHTTPFetcherCookieStorageMethodStatic
00471 // without a fetch history set, and kGTMHTTPFetcherCookieStorageMethodFetchHistory
00472 // with a fetch history set
00473 //
00474 // Applications needing control of cookies across a sequence of fetches should
00475 // create fetchers from a GTMHTTPFetcherService object (which encapsulates
00476 // fetch history) for a well-defined cookie store
00477 @property (assign) NSInteger cookieStorageMethod;
00478 
00479 + (id <GTMCookieStorageProtocol>)staticCookieStorage;
00480 
00481 // Object to add authorization to the request, if needed
00482 @property (retain) id <GTMFetcherAuthorizationProtocol> authorizer;
00483 
00484 // The service object that created and monitors this fetcher, if any
00485 @property (retain) id <GTMHTTPFetcherServiceProtocol> service;
00486 
00487 // The host, if any, used to classify this fetcher in the fetcher service
00488 @property (copy) NSString *serviceHost;
00489 
00490 // The priority, if any, used for starting fetchers in the fetcher service
00491 //
00492 // Lower values are higher priority; the default is 0, and values may
00493 // be negative or positive. This priority affects only the start order of
00494 // fetchers that are being delayed by a fetcher service.
00495 @property (assign) NSInteger servicePriority;
00496 
00497 // The thread used to run this fetcher in the fetcher service
00498 @property (retain) NSThread *thread;
00499 
00500 // The delegate is retained during the connection
00501 @property (retain) id delegate;
00502 
00503 // On iOS 4 and later, the fetch may optionally continue while the app is in the
00504 // background until finished or stopped by OS expiration
00505 //
00506 // The default value is NO
00507 //
00508 // For Mac OS X, background fetches are always supported, and this property
00509 // is ignored
00510 @property (assign) BOOL shouldFetchInBackground;
00511 
00512 // The delegate's optional sentData selector may be used to monitor upload
00513 // progress. It should have a signature like:
00514 //  - (void)myFetcher:(GTMHTTPFetcher *)fetcher
00515 //              didSendBytes:(NSInteger)bytesSent
00516 //            totalBytesSent:(NSInteger)totalBytesSent
00517 //  totalBytesExpectedToSend:(NSInteger)totalBytesExpectedToSend;
00518 //
00519 // +doesSupportSentDataCallback indicates if this delegate method is supported
00520 + (BOOL)doesSupportSentDataCallback;
00521 
00522 @property (assign) SEL sentDataSelector;
00523 
00524 // The delegate's optional receivedData selector may be used to monitor download
00525 // progress. It should have a signature like:
00526 //  - (void)myFetcher:(GTMHTTPFetcher *)fetcher
00527 //       receivedData:(NSData *)dataReceivedSoFar;
00528 //
00529 // The dataReceived argument will be nil when downloading to a path or to a
00530 // file handle.
00531 //
00532 // Applications should not use this method to accumulate the received data;
00533 // the callback method or block supplied to the beginFetch call will have
00534 // the complete NSData received.
00535 @property (assign) SEL receivedDataSelector;
00536 
00537 #if NS_BLOCKS_AVAILABLE
00538 // The full interface to the block is provided rather than just a typedef for
00539 // its parameter list in order to get more useful code completion in the Xcode
00540 // editor
00541 @property (copy) void (^sentDataBlock)(NSInteger bytesSent, NSInteger totalBytesSent, NSInteger bytesExpectedToSend);
00542 
00543 // The dataReceived argument will be nil when downloading to a path or to
00544 // a file handle
00545 @property (copy) void (^receivedDataBlock)(NSData *dataReceivedSoFar);
00546 #endif
00547 
00548 // retrying; see comments at the top of the file.  Calling
00549 // setRetryEnabled(YES) resets the min and max retry intervals.
00550 @property (assign, getter=isRetryEnabled) BOOL retryEnabled;
00551 
00552 // Retry selector or block is optional for retries.
00553 //
00554 // If present, it should have the signature:
00555 //   -(BOOL)fetcher:(GTMHTTPFetcher *)fetcher willRetry:(BOOL)suggestedWillRetry forError:(NSError *)error
00556 // and return YES to cause a retry.  See comments at the top of this file.
00557 @property (assign) SEL retrySelector;
00558 
00559 #if NS_BLOCKS_AVAILABLE
00560 @property (copy) BOOL (^retryBlock)(BOOL suggestedWillRetry, NSError *error);
00561 #endif
00562 
00563 // Retry intervals must be strictly less than maxRetryInterval, else
00564 // they will be limited to maxRetryInterval and no further retries will
00565 // be attempted.  Setting maxRetryInterval to 0.0 will reset it to the
00566 // default value, 600 seconds.
00567 
00568 @property (assign) NSTimeInterval maxRetryInterval;
00569 
00570 // Starting retry interval.  Setting minRetryInterval to 0.0 will reset it
00571 // to a random value between 1.0 and 2.0 seconds.  Clients should normally not
00572 // call this except for unit testing.
00573 @property (assign) NSTimeInterval minRetryInterval;
00574 
00575 // Multiplier used to increase the interval between retries, typically 2.0.
00576 // Clients should not need to call this.
00577 @property (assign) double retryFactor;
00578 
00579 // Number of retries attempted
00580 @property (readonly) NSUInteger retryCount;
00581 
00582 // interval delay to precede next retry
00583 @property (readonly) NSTimeInterval nextRetryInterval;
00584 
00585 // Begin fetching the request
00586 //
00587 // The delegate can optionally implement the finished selectors or pass NULL
00588 // for it.
00589 //
00590 // Returns YES if the fetch is initiated.  The delegate is retained between
00591 // the beginFetch call until after the finish callback.
00592 //
00593 // An error is passed to the callback for server statuses 300 or
00594 // higher, with the status stored as the error object's code.
00595 //
00596 // finishedSEL has a signature like:
00597 //   - (void)fetcher:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *)error;
00598 //
00599 // If the application has specified a downloadPath or downloadFileHandle
00600 // for the fetcher, the data parameter passed to the callback will be nil.
00601 
00602 - (BOOL)beginFetchWithDelegate:(id)delegate
00603              didFinishSelector:(SEL)finishedSEL;
00604 
00605 #if NS_BLOCKS_AVAILABLE
00606 - (BOOL)beginFetchWithCompletionHandler:(void (^)(NSData *data, NSError *error))handler;
00607 #endif
00608 
00609 
00610 // Returns YES if this is in the process of fetching a URL
00611 - (BOOL)isFetching;
00612 
00613 // Cancel the fetch of the request that's currently in progress
00614 - (void)stopFetching;
00615 
00616 // Return the status code from the server response
00617 @property (readonly) NSInteger statusCode;
00618 
00619 // Return the http headers from the response
00620 @property (retain, readonly) NSDictionary *responseHeaders;
00621 
00622 // The response, once it's been received
00623 @property (retain) NSURLResponse *response;
00624 
00625 // Bytes downloaded so far
00626 @property (readonly) unsigned long long downloadedLength;
00627 
00628 // Buffer of currently-downloaded data
00629 @property (readonly, retain) NSData *downloadedData;
00630 
00631 // Path in which to non-atomically create a file for storing the downloaded data
00632 //
00633 // The path must be set before fetching begins.  The download file handle
00634 // will be created for the path, and can be used to monitor progress. If a file
00635 // already exists at the path, it will be overwritten.
00636 @property (copy) NSString *downloadPath;
00637 
00638 // If downloadFileHandle is set, data received is immediately appended to
00639 // the file handle rather than being accumulated in the downloadedData property
00640 //
00641 // The file handle supplied must allow writing and support seekToFileOffset:,
00642 // and must be set before fetching begins.  Setting a download path will
00643 // override the file handle property.
00644 @property (retain) NSFileHandle *downloadFileHandle;
00645 
00646 // The optional fetchHistory object is used for a sequence of fetchers to
00647 // remember ETags, cache ETagged data, and store cookies.  Typically, this
00648 // is set by a GTMFetcherService object when it creates a fetcher.
00649 //
00650 // Side effect: setting fetch history implicitly calls setCookieStorageMethod:
00651 @property (retain) id <GTMHTTPFetchHistoryProtocol> fetchHistory;
00652 
00653 // userData is retained for the convenience of the caller
00654 @property (retain) id userData;
00655 
00656 // Stored property values are retained for the convenience of the caller
00657 @property (copy) NSMutableDictionary *properties;
00658 
00659 - (void)setProperty:(id)obj forKey:(NSString *)key; // pass nil obj to remove property
00660 - (id)propertyForKey:(NSString *)key;
00661 
00662 - (void)addPropertiesFromDictionary:(NSDictionary *)dict;
00663 
00664 // Comments are useful for logging
00665 @property (copy) NSString *comment;
00666 
00667 - (void)setCommentWithFormat:(id)format, ...;
00668 
00669 // Log of request and response, if logging is enabled
00670 @property (copy) NSString *log;
00671 
00672 // Using the fetcher while a modal dialog is displayed requires setting the
00673 // run-loop modes to include NSModalPanelRunLoopMode
00674 @property (retain) NSArray *runLoopModes;
00675 
00676 // Users who wish to replace GTMHTTPFetcher's use of NSURLConnection
00677 // can do so globally here.  The replacement should be a subclass of
00678 // NSURLConnection.
00679 + (Class)connectionClass;
00680 + (void)setConnectionClass:(Class)theClass;
00681 
00682 // Spin the run loop, discarding events, until the fetch has completed
00683 //
00684 // This is only for use in testing or in tools without a user interface.
00685 //
00686 // Synchronous fetches should never be done by shipping apps; they are
00687 // sufficient reason for rejection from the app store.
00688 - (void)waitForCompletionWithTimeout:(NSTimeInterval)timeoutInSeconds;
00689 
00690 #if STRIP_GTM_FETCH_LOGGING
00691 // if logging is stripped, provide a stub for the main method
00692 // for controlling logging
00693 + (void)setLoggingEnabled:(BOOL)flag;
00694 #endif // STRIP_GTM_FETCH_LOGGING
00695 
00696 @end