Home | History | Annotate | Download | only in ios
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #if !defined(__has_feature) || !__has_feature(objc_arc)
      6 #error "This file requires ARC support."
      7 #endif
      8 
      9 #import "remoting/ios/host_refresh.h"
     10 
     11 #import "remoting/ios/authorize.h"
     12 #import "remoting/ios/host.h"
     13 #import "remoting/ios/utility.h"
     14 
     15 namespace {
     16 NSString* kDefaultErrorMessage = @"The Host list refresh is not available at "
     17     @"this time.  Please try again later.";
     18 }  // namespace
     19 
     20 @interface HostRefresh (Private)
     21 - (void)authentication:(GTMOAuth2Authentication*)auth
     22                request:(NSMutableURLRequest*)request
     23                  error:(NSError*)error;
     24 - (void)formatErrorMessage:(NSString*)error;
     25 - (void)notifyDelegate;
     26 @end
     27 
     28 // Logic flow begins with refreshHostList, and continues until an error occurs,
     29 // or the host list is returned to the delegate
     30 @implementation HostRefresh
     31 
     32 @synthesize jsonData = _jsonData;
     33 @synthesize errorMessage = _errorMessage;
     34 @synthesize delegate = _delegate;
     35 
     36 // Override default constructor and initialize internals
     37 - (id)init {
     38   self = [super init];
     39   if (self) {
     40     _jsonData = [[NSMutableData alloc] init];
     41   }
     42   return self;
     43 }
     44 
     45 // Begin the authentication and authorization process.  Begin the process by
     46 // creating an oAuth2 request to google api's including the needed scopes to
     47 // fetch the users host list.
     48 - (void)refreshHostList:(GTMOAuth2Authentication*)authReq
     49                delegate:(id<HostRefreshDelegate>)delegate {
     50 
     51   CHECK(_delegate == nil);  // Do not reuse an instance of this class
     52 
     53   _delegate = delegate;
     54 
     55   [Authorize beginRequest:authReq
     56                  delegate:self
     57         didFinishSelector:@selector(authentication:request:error:)];
     58 }
     59 
     60 // Handle completion of the authorization process. Append service credentials
     61 // for jabber.  If an error occurred, notify user.
     62 - (void)authentication:(NSObject*)auth
     63                request:(NSMutableURLRequest*)request
     64                  error:(NSError*)error {
     65   if (error != nil) {
     66     [self formatErrorMessage:error.localizedDescription];
     67   } else {
     68     // Add credentials for service
     69     [Authorize appendCredentials:request];
     70 
     71     // Begin connection, the returned reference is not useful right now and
     72     // marked as __unused
     73     __unused NSURLConnection* connection =
     74         [[NSURLConnection alloc] initWithRequest:request delegate:self];
     75   }
     76 }
     77 
     78 // @protocol NSURLConnectionDelegate, handle any error during connection
     79 - (void)connection:(NSURLConnection*)connection
     80     didFailWithError:(NSError*)error {
     81   [self formatErrorMessage:[error localizedDescription]];
     82 
     83   [self notifyDelegate];
     84 }
     85 
     86 // @protocol NSURLConnectionDataDelegate, may be called async multiple times.
     87 // Each call appends the new data to the known data until completed.
     88 - (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data {
     89   [_jsonData appendData:data];
     90 }
     91 
     92 // @protocol NSURLConnectionDataDelegate
     93 // Ensure connection succeeded: HTTP 200 OK
     94 - (void)connection:(NSURLConnection*)connection
     95     didReceiveResponse:(NSURLResponse*)response {
     96   NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
     97   if ([response respondsToSelector:@selector(allHeaderFields)]) {
     98     NSNumber* responseCode =
     99         [[NSNumber alloc] initWithInteger:[httpResponse statusCode]];
    100     if (responseCode.intValue != 200) {
    101       [self formatErrorMessage:[NSString
    102                                    stringWithFormat:@"HTTP STATUS CODE: %d",
    103                                                     [httpResponse statusCode]]];
    104     }
    105   }
    106 }
    107 
    108 // @protocol NSURLConnectionDataDelegate handle a completed connection, parse
    109 // received data, and return host list to delegate
    110 - (void)connectionDidFinishLoading:(NSURLConnection*)connection {
    111   [self notifyDelegate];
    112 }
    113 
    114 // Store a formatted error message to return later
    115 - (void)formatErrorMessage:(NSString*)error {
    116   _errorMessage = kDefaultErrorMessage;
    117   if (error != nil && error.length > 0) {
    118     _errorMessage = [_errorMessage
    119         stringByAppendingString:[@" " stringByAppendingString:error]];
    120   }
    121 }
    122 
    123 // The connection has finished, call to delegate
    124 - (void)notifyDelegate {
    125   if (_jsonData.length == 0 && _errorMessage == nil) {
    126     [self formatErrorMessage:nil];
    127   }
    128 
    129   [_delegate hostListRefresh:[Host parseListFromJSON:_jsonData]
    130                 errorMessage:_errorMessage];
    131 }
    132 @end
    133