Chromium Code Reviews| Index: remoting/ios/host_refresh.mm |
| diff --git a/remoting/ios/host_refresh.mm b/remoting/ios/host_refresh.mm |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..eddfcaad109179530312bd8432a3bb26d04ab091 |
| --- /dev/null |
| +++ b/remoting/ios/host_refresh.mm |
| @@ -0,0 +1,195 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#if !defined(__has_feature) || !__has_feature(objc_arc) |
| +#error "This file requires ARC support." |
| +#endif |
| + |
| +#import "remoting/ios/host_refresh.h" |
| + |
| +#import "remoting/ios/host.h" |
| +#import "remoting/ios/utility.h" |
| + |
| +@interface HostRefresh (Private) |
| +- (void)authentication:(GTMOAuth2Authentication*)auth |
| + request:(NSMutableURLRequest*)request |
| + error:(NSError*)error; |
| ++ (NSMutableArray*)parseJSON:(NSMutableData*)data; |
| ++ (void)setNetworkActivityIndicator:(BOOL)show; |
| ++ (void)callFailed:(NSString*)error; |
| +@end |
| + |
| +// Logic flow begins with refreshHostList, and continutes until an error occurs, |
| +// or the host list is returned to the delegate |
| +@implementation HostRefresh |
| + |
| +// Begin the authentication and authorization process. Begin the process by |
| +// createing an oAuth2 request to google api's including the needed scopes to |
|
dcaiafa
2014/03/19 01:14:15
nit: spelling
aboone
2014/03/21 16:42:07
Done.
|
| +// fetch the users host list. |
| +- (void)refreshHostList:(GTMOAuth2Authentication*)authReq |
| + delegate:(id<HostRefreshDelegate>)delegate { |
| + _jsonData = [[NSMutableData alloc] init]; |
| + _delegate = delegate; |
| + |
| + // Build request URL using API HTTP endpoint, and our api key |
| + NSMutableString* urlStr = [[NSMutableString alloc] init]; |
| + [urlStr |
| + appendFormat: |
| + @"%@%@%@", |
| + [NSString stringWithUTF8String:remoting::ServiceUrls::GetInstance() |
|
dcaiafa
2014/03/19 01:14:15
Store intermediate values in locals to improve rea
aboone
2014/03/21 16:42:07
Done.
|
| + ->directory_hosts_url() |
| + .c_str()], |
| + @"?key=", |
| + [NSString stringWithUTF8String:google_apis::GetAPIKey().c_str()]]; |
| + NSURL* url = [NSURL URLWithString:urlStr]; |
| + NSMutableURLRequest* theRequest = [NSMutableURLRequest requestWithURL:url]; |
| + |
| + // Add scopes if needed |
| + NSString* scope = authReq.scope; |
| + if ([scope rangeOfString:[NSString stringWithUTF8String: |
| + remoting::GetOauthScope().c_str()]] |
| + .location == NSNotFound) { |
| + scope = [GTMOAuth2Authentication |
| + scopeWithStrings: |
| + scope, |
| + [NSString stringWithUTF8String:remoting::GetOauthScope().c_str()], |
| + nil]; |
| + authReq.scope = scope; |
| + } |
| + // Execute request async |
| + [authReq authorizeRequest:theRequest |
| + delegate:self |
| + didFinishSelector:@selector(authentication:request:error:)]; |
| + |
| + [HostRefresh setNetworkActivityIndicator:YES]; |
| +} |
| + |
| +// Handle completion of the authorization process. Append service credientals |
| +// for jabber. If an error occured, notify user. |
| +- (void)authentication:(GTMOAuth2Authentication*)auth |
| + request:(NSMutableURLRequest*)request |
| + error:(NSError*)error { |
| + [HostRefresh setNetworkActivityIndicator:NO]; |
| + if (error != nil) { |
| + [HostRefresh callFailed:error.localizedDescription]; |
| + } else { |
| + // Add credientails for service |
| + [request addValue:[NSString stringWithUTF8String: |
| + google_apis::GetOAuth2ClientID( |
| + google_apis::CLIENT_REMOTING).c_str()] |
| + forHTTPHeaderField:@"client_id"]; |
| + [request addValue:[NSString stringWithUTF8String: |
| + google_apis::GetOAuth2ClientSecret( |
| + google_apis::CLIENT_REMOTING).c_str()] |
| + forHTTPHeaderField:@"client_secret"]; |
| + |
| + // Begin connection, the returned reference is not useful right now and |
| + // marked as __unused |
| + __unused NSURLConnection* connection = |
| + [[NSURLConnection alloc] initWithRequest:request delegate:self]; |
| + [HostRefresh setNetworkActivityIndicator:YES]; |
| + } |
| +} |
| + |
| +// @protocol NSURLConnectionDelegate, handle any error during connection |
| +- (void)connection:(NSURLConnection*)connection |
| + didFailWithError:(NSError*)error { |
| + [HostRefresh setNetworkActivityIndicator:NO]; |
| + [HostRefresh callFailed:[error localizedDescription]]; |
| + |
| + // if we have any _jsonData go ahead and release it |
| + [_jsonData setLength:0]; |
| +} |
| + |
| +// @protocol NSURLConnectionDataDelegate, may be called async multiple times. |
| +// Each call appeads the new data to the known data until completed. |
| +- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data { |
| + [_jsonData appendData:data]; |
| +} |
| + |
| +// @protocol NSURLConnectionDataDelegate |
| +// Ensure connection succeeded: HTTP 200 OK |
| +- (void)connection:(NSURLConnection*)connection |
| + didReceiveResponse:(NSURLResponse*)response { |
| + NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response; |
| + if ([response respondsToSelector:@selector(allHeaderFields)]) { |
| + NSNumber* responseCode = |
| + [[NSNumber alloc] initWithInteger:[httpResponse statusCode]]; |
| + if (responseCode.intValue != 200) { |
| + |
| + // if we have any _jsonData go ahead and release it |
| + [_jsonData setLength:0]; |
| + [HostRefresh |
| + callFailed:[NSString stringWithFormat:@"HTTP STATUS CODE: %d", |
| + [httpResponse statusCode]]]; |
| + } |
| + } |
| +} |
| + |
| +// @protocol NSURLConnectionDataDelegate handle a completed connection, parse |
| +// received data, and return host list to delagate |
| +- (void)connectionDidFinishLoading:(NSURLConnection*)connection { |
| + [HostRefresh setNetworkActivityIndicator:NO]; |
| + if ([_jsonData length] == 0 || _delegate == nil) { |
| + [HostRefresh callFailed:nil]; |
| + } |
| + [_delegate hostListRefresh:[HostRefresh parseJSON:_jsonData]]; |
| + |
| + // Done with the data, release it |
| + [_jsonData setLength:0]; |
| +} |
| + |
| +// Parse jsonData into Host list |
| ++ (NSMutableArray*)parseJSON:(NSMutableData*)data { |
| + NSError* error; |
| + NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data |
| + options:kNilOptions |
| + error:&error]; |
| + |
| + NSDictionary* dataDict = [json objectForKey:@"data"]; |
| + |
| + NSArray* availableServers = [dataDict objectForKey:@"items"]; |
| + |
| + NSMutableArray* serverList = [[NSMutableArray alloc] init]; |
| + |
| + NSUInteger idx = 0; |
| + NSDictionary* svr; |
| + NSUInteger count = [availableServers count]; |
| + |
| + while (idx < count) { |
| + svr = [availableServers objectAtIndex:idx++]; |
| + Host* host = [[Host alloc] init]; |
| + host.createdTime = [svr objectForKey:@"createdTime"]; |
| + host.hostId = [svr objectForKey:@"hostId"]; |
| + host.hostName = [svr objectForKey:@"hostName"]; |
| + host.hostVersion = [svr objectForKey:@"hostVersion"]; |
| + host.jabberId = [svr objectForKey:@"jabberId"]; |
| + host.kind = [svr objectForKey:@"kind"]; |
| + host.publicKey = [svr objectForKey:@"publicKey"]; |
| + host.status = [svr objectForKey:@"status"]; |
| + host.updatedTime = [svr objectForKey:@"updatedTime"]; |
| + [serverList addObject:host]; |
| + } |
| + |
| + return serverList; |
| +} |
| + |
| +// Request 'wait' annimation from application |
| ++ (void)setNetworkActivityIndicator:(BOOL)show { |
| + [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:show]; |
| +} |
| + |
| +// Notifiy user with an error message |
| ++ (void)callFailed:(NSString*)error { |
| + NSString* errorMsg = @"The Host list refresh is not available at this time. " |
| + " Please try again later."; |
| + if (error != nil && error.length > 0) { |
| + errorMsg = |
| + [errorMsg stringByAppendingString:[@" " stringByAppendingString:error]]; |
| + } |
| + |
| + [Utility showAlert:@"Host Refresh Failed" message:errorMsg]; |
| +} |
| + |
| +@end |