Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(488)

Side by Side Diff: remoting/client/ios/facade/remoting_service.mm

Issue 2854273002: [CRD iOS] Implementing save to keychain and user defaults for login info. Refactor remoting service. (Closed)
Patch Set: Removing authenticate with refresh token from pub api. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « remoting/client/ios/facade/remoting_service.h ('k') | remoting/client/ios/keychain_wrapper.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if !defined(__has_feature) || !__has_feature(objc_arc) 5 #if !defined(__has_feature) || !__has_feature(objc_arc)
6 #error "This file requires ARC support." 6 #error "This file requires ARC support."
7 #endif 7 #endif
8 8
9 #import "remoting/client/ios/facade/remoting_service.h" 9 #import "remoting/client/ios/facade/remoting_service.h"
10 10
11 #import <Foundation/Foundation.h> 11 #import <Foundation/Foundation.h>
12 #import <Security/Security.h>
12 13
13 #import "base/mac/bind_objc_block.h" 14 #import "base/mac/bind_objc_block.h"
15 #import "remoting/client/ios/domain/host_info.h"
16 #import "remoting/client/ios/domain/user_info.h"
17 #import "remoting/client/ios/facade/host_info.h"
18 #import "remoting/client/ios/facade/host_list_fetcher.h"
19 #import "remoting/client/ios/facade/ios_client_runtime_delegate.h"
20 #import "remoting/client/ios/facade/remoting_authentication.h"
21 #import "remoting/client/ios/facade/remoting_service.h"
22 #import "remoting/client/ios/keychain_wrapper.h"
14 23
15 #include "base/logging.h" 24 #include "base/logging.h"
16 #include "base/strings/sys_string_conversions.h" 25 #include "base/strings/sys_string_conversions.h"
17 #include "net/url_request/url_request_context_getter.h" 26 #include "net/url_request/url_request_context_getter.h"
18 #include "remoting/base/oauth_token_getter.h" 27 #include "remoting/base/oauth_token_getter.h"
19 #include "remoting/base/oauth_token_getter_impl.h" 28 #include "remoting/base/oauth_token_getter_impl.h"
20 #include "remoting/client/ios/facade/host_info.h"
21 #include "remoting/client/ios/facade/host_list_fetcher.h"
22 #include "remoting/client/ios/facade/ios_client_runtime_delegate.h"
23 29
24 const char kOauthRedirectUrl[] = 30 static NSString* const kCRDAuthenticatedUserEmailKey =
25 "https://chromoting-oauth.talkgadget." 31 @"kCRDAuthenticatedUserEmailKey";
26 "google.com/talkgadget/oauth/chrome-remote-desktop/dev";
27 32
28 std::unique_ptr<remoting::OAuthTokenGetter> 33 NSString* const kHostsDidUpdate = @"kHostsDidUpdate";
29 CreateOAuthTokenGetterWithAuthorizationCode(
30 const std::string& auth_code,
31 const remoting::OAuthTokenGetter::CredentialsUpdatedCallback&
32 on_credentials_update) {
33 std::unique_ptr<remoting::OAuthTokenGetter::OAuthIntermediateCredentials>
34 oauth_credentials(
35 new remoting::OAuthTokenGetter::OAuthIntermediateCredentials(
36 auth_code, /*is_service_account=*/false));
37 oauth_credentials->oauth_redirect_uri = kOauthRedirectUrl;
38 34
39 std::unique_ptr<remoting::OAuthTokenGetter> oauth_tokenGetter( 35 NSString* const kUserDidUpdate = @"kUserDidUpdate";
40 new remoting::OAuthTokenGetterImpl( 36 NSString* const kUserInfo = @"kUserInfo";
41 std::move(oauth_credentials), on_credentials_update,
42 [[RemotingService SharedInstance] runtime]->url_requester(),
43 /*auto_refresh=*/true));
44 return oauth_tokenGetter;
45 }
46 37
47 std::unique_ptr<remoting::OAuthTokenGetter> CreateOAuthTokenWithRefreshToken( 38 @interface RemotingService ()<RemotingAuthenticationDelegate> {
48 const std::string& refresh_token,
49 const std::string& email) {
50 std::unique_ptr<remoting::OAuthTokenGetter::OAuthAuthorizationCredentials>
51 oauth_credentials(
52 new remoting::OAuthTokenGetter::OAuthAuthorizationCredentials(
53 email, refresh_token, /*is_service_account=*/false));
54
55 std::unique_ptr<remoting::OAuthTokenGetter> oauth_tokenGetter(
56 new remoting::OAuthTokenGetterImpl(
57 std::move(oauth_credentials),
58 [[RemotingService SharedInstance] runtime]->url_requester(),
59 /*auto_refresh=*/true));
60 return oauth_tokenGetter;
61 }
62
63 @interface RemotingService () {
64 std::unique_ptr<remoting::OAuthTokenGetter> _tokenGetter; 39 std::unique_ptr<remoting::OAuthTokenGetter> _tokenGetter;
65 UserInfo* _user;
66 NSArray<HostInfo*>* _hosts;
67 id<RemotingAuthenticationDelegate> _authDelegate;
68 id<RemotingHostListDelegate> _hostListDelegate;
69 remoting::HostListFetcher* _hostListFetcher; 40 remoting::HostListFetcher* _hostListFetcher;
70 remoting::IosClientRuntimeDelegate* _clientRuntimeDelegate; 41 remoting::IosClientRuntimeDelegate* _clientRuntimeDelegate;
71 } 42 }
72
73 @end 43 @end
74 44
75 //
76 // RemodingService will act as the facade to the C++ layer that has not been
77 // implemented/integrated yet.
78 // TODO(nicholss): Implement/Integrate this class. At the moment it is being
79 // used to generate fake data to implement the UI of the app.
80 // Update: Half implemented now. User is still fake, but now real hosts lists.
81 //
82 @implementation RemotingService 45 @implementation RemotingService
83 46
47 @synthesize authentication = _authentication;
48 @synthesize hosts = _hosts;
49
84 // RemotingService is a singleton. 50 // RemotingService is a singleton.
85 + (RemotingService*)SharedInstance { 51 + (RemotingService*)SharedInstance {
86 static RemotingService* sharedInstance = nil; 52 static RemotingService* sharedInstance = nil;
87 static dispatch_once_t guard; 53 static dispatch_once_t guard;
88 dispatch_once(&guard, ^{ 54 dispatch_once(&guard, ^{
89 sharedInstance = [[RemotingService alloc] init]; 55 sharedInstance = [[RemotingService alloc] init];
90 }); 56 });
91 return sharedInstance; 57 return sharedInstance;
92 } 58 }
93 59
94 - (instancetype)init { 60 - (instancetype)init {
95 self = [super init]; 61 self = [super init];
96 if (self) { 62 if (self) {
97 _user = nil; 63 _authentication = [[RemotingAuthentication alloc] init];
64 _authentication.delegate = self;
98 _hosts = nil; 65 _hosts = nil;
99 _hostListFetcher = new remoting::HostListFetcher( 66 _hostListFetcher = nil;
100 remoting::ChromotingClientRuntime::GetInstance()->url_requester());
101 // TODO(nicholss): This might need a pointer back to the service. 67 // TODO(nicholss): This might need a pointer back to the service.
102 _clientRuntimeDelegate = 68 _clientRuntimeDelegate =
103 new remoting::IosClientRuntimeDelegate(); 69 new remoting::IosClientRuntimeDelegate();
104 [self runtime]->SetDelegate(_clientRuntimeDelegate); 70 [self runtime]->SetDelegate(_clientRuntimeDelegate);
105 } 71 }
106 return self; 72 return self;
107 } 73 }
108 74
109 #pragma mark - RemotingService Implementation 75 #pragma mark - RemotingService Implementation
110 76
111 // TODO(nicholss): isAuthenticated needs to just kick off a request to 77 - (void)startHostListFetchWith:(NSString*)accessToken {
112 // authenticate a user. and more than one controller might want to be a delegate 78 if (!_hostListFetcher) {
113 // for this info so need to change this to be more of the registration types. 79 _hostListFetcher = new remoting::HostListFetcher(
114 // The remoting_service might also want to be registered for authentication 80 remoting::ChromotingClientRuntime::GetInstance()->url_requester());
115 // changes and it can update it's cache as it needs.
116
117 - (void)setAuthenticationDelegate:(id<RemotingAuthenticationDelegate>)delegate {
118 _authDelegate = delegate;
119 if (_authDelegate) {
120 [_authDelegate nowAuthenticated:[self isAuthenticated]];
121 } 81 }
122 if (!_user && _tokenGetter) { 82 _hostListFetcher->RetrieveHostlist(
123 _tokenGetter->CallWithToken(base::BindBlockArc( 83 base::SysNSStringToUTF8(accessToken),
124 ^(remoting::OAuthTokenGetter::Status status, 84 base::BindBlockArc(^(const std::vector<remoting::HostInfo>& hostlist) {
125 const std::string& user_email, const std::string& access_token) { 85 NSMutableArray<HostInfo*>* hosts =
126 if (status == remoting::OAuthTokenGetter::Status::SUCCESS) { 86 [NSMutableArray arrayWithCapacity:hostlist.size()];
127 _user = [[UserInfo alloc] init]; 87 std::string status;
128 _user.userEmail = 88 for (const remoting::HostInfo& host_info : hostlist) {
129 [NSString stringWithCString:user_email.c_str() 89 remoting::HostStatus host_status = host_info.status;
130 encoding:[NSString defaultCStringEncoding]]; 90 switch (host_status) {
131 } else { 91 case remoting::kHostStatusOnline:
132 _user = nil; 92 status = "ONLINE";
93 break;
94 case remoting::kHostStatusOffline:
95 status = "OFFLINE";
96 break;
97 default:
98 NOTREACHED();
133 } 99 }
134 if (_authDelegate) { 100 // TODO(nicholss): Not yet integrated: createdTime, hostVersion,
135 [_authDelegate nowAuthenticated:[self isAuthenticated]]; 101 // kind, offlineReason. Add them as the app will need this info.
136 } 102 HostInfo* host = [[HostInfo alloc] init];
137 })); 103 host.hostId =
138 } 104 [NSString stringWithCString:host_info.host_id.c_str()
105 encoding:[NSString defaultCStringEncoding]];
106 host.hostName =
107 [NSString stringWithCString:host_info.host_name.c_str()
108 encoding:[NSString defaultCStringEncoding]];
109 host.jabberId =
110 [NSString stringWithCString:host_info.host_jid.c_str()
111 encoding:[NSString defaultCStringEncoding]];
112 host.publicKey =
113 [NSString stringWithCString:host_info.public_key.c_str()
114 encoding:[NSString defaultCStringEncoding]];
115 host.status =
116 [NSString stringWithCString:status.c_str()
117 encoding:[NSString defaultCStringEncoding]];
118 [hosts addObject:host];
119 }
120 _hosts = hosts;
121 [self hostListUpdated];
122 }));
139 } 123 }
140 124
141 - (BOOL)isAuthenticated { 125 #pragma mark - Notifications
142 if (_user) { 126
143 return YES; 127 - (void)hostListUpdated {
144 } 128 [[NSNotificationCenter defaultCenter] postNotificationName:kHostsDidUpdate
145 return NO; 129 object:self
130 userInfo:nil];
146 } 131 }
147 132
148 - (void)startHostListFetchWith:(NSString*)accessToken { 133 #pragma mark - RemotingAuthenticationDelegate
149 NSLog(@"startHostListFetchWith : %@ %@", accessToken, _authDelegate);
150 if (_authDelegate) {
151 [_authDelegate nowAuthenticated:YES];
152 134
153 _hostListFetcher->RetrieveHostlist( 135 - (void)userDidUpdate:(UserInfo*)user {
154 base::SysNSStringToUTF8(accessToken), 136 NSDictionary* userInfo = nil;
155 base::BindBlockArc(^(const std::vector<remoting::HostInfo>& hostlist) { 137 if (user) {
156 NSMutableArray<HostInfo*>* hosts = 138 userInfo = [NSDictionary dictionaryWithObject:user forKey:kUserInfo];
157 [NSMutableArray arrayWithCapacity:hostlist.size()]; 139 } else {
158 std::string status; 140 _hosts = nil;
159 for (const remoting::HostInfo& host_info : hostlist) { 141 [self hostListUpdated];
160 remoting::HostStatus host_status = host_info.status;
161 switch (host_status) {
162 case remoting::kHostStatusOnline:
163 status = "ONLINE";
164 break;
165 case remoting::kHostStatusOffline:
166 status = "OFFLINE";
167 break;
168 default:
169 NOTREACHED();
170 }
171 // TODO(nicholss): Not yet integrated: createdTime, hostVersion,
172 // kind, offlineReason. Add them as the app will need this info.
173 HostInfo* host = [[HostInfo alloc] init];
174 host.hostId =
175 [NSString stringWithCString:host_info.host_id.c_str()
176 encoding:[NSString defaultCStringEncoding]];
177 host.hostName =
178 [NSString stringWithCString:host_info.host_name.c_str()
179 encoding:[NSString defaultCStringEncoding]];
180 host.jabberId =
181 [NSString stringWithCString:host_info.host_jid.c_str()
182 encoding:[NSString defaultCStringEncoding]];
183 host.publicKey =
184 [NSString stringWithCString:host_info.public_key.c_str()
185 encoding:[NSString defaultCStringEncoding]];
186 host.status =
187 [NSString stringWithCString:status.c_str()
188 encoding:[NSString defaultCStringEncoding]];
189 [hosts addObject:host];
190 }
191 _hosts = hosts;
192 [_hostListDelegate hostListUpdated];
193 }));
194 } 142 }
143 [[NSNotificationCenter defaultCenter] postNotificationName:kUserDidUpdate
144 object:self
145 userInfo:userInfo];
195 } 146 }
196 147
197 - (void)authenticateWithAuthorizationCode:(NSString*)authorizationCode { 148 #pragma mark - Properties
198 _tokenGetter = CreateOAuthTokenGetterWithAuthorizationCode(
199 std::string(base::SysNSStringToUTF8(authorizationCode)),
200 base::BindBlockArc(
201 ^(const std::string& user_email, const std::string& refresh_token) {
202 // TODO(nicholss): Do something with these new creds.
203 VLOG(1) << "New Creds: " << user_email << " " << refresh_token;
204 }));
205 }
206 149
207 - (void)authenticateWithRefreshToken:(NSString*)refreshToken 150 - (NSArray<HostInfo*>*)hosts {
208 email:(NSString*)email { 151 if ([_authentication.user isAuthenticated]) {
209 _tokenGetter = CreateOAuthTokenWithRefreshToken( 152 return _hosts;
210 std::string(base::SysNSStringToUTF8(refreshToken)),
211 base::SysNSStringToUTF8(email));
212 }
213
214 - (UserInfo*)getUser {
215 if (![self isAuthenticated]) {
216 return nil;
217 } 153 }
218 154 return nil;
219 NSMutableString* json = [[NSMutableString alloc] init];
220 [json appendString:@"{"];
221 [json appendString:@"\"userId\":\"AABBCC123\","];
222 [json appendString:@"\"userFullName\":\"John Smith\","];
223 [json appendString:@"\"userEmail\":\"john@example.com\","];
224 [json appendString:@"}"];
225
226 NSMutableData* data = [NSMutableData
227 dataWithData:[[json copy] dataUsingEncoding:NSUTF8StringEncoding]];
228
229 UserInfo* user = [UserInfo parseListFromJSON:data];
230 return user;
231 }
232
233 - (void)setHostListDelegate:(id<RemotingHostListDelegate>)delegate {
234 bool attemptUpdate = (_hostListDelegate != delegate);
235 _hostListDelegate = delegate;
236 if (attemptUpdate && _hostListDelegate && _tokenGetter) {
237 // TODO(nicholss): It might be cleaner to set the delegate and then have
238 // them ask to refresh the host list rather than start this get hosts call.
239 _tokenGetter->CallWithToken(base::BindBlockArc(
240 ^(remoting::OAuthTokenGetter::Status status,
241 const std::string& user_email, const std::string& access_token) {
242 NSString* accessToken =
243 [NSString stringWithCString:access_token.c_str()
244 encoding:[NSString defaultCStringEncoding]];
245 [self startHostListFetchWith:accessToken];
246 }));
247 }
248 }
249
250 - (NSArray<HostInfo*>*)getHosts {
251 if (![self isAuthenticated]) {
252 return nil;
253 }
254 return _hosts;
255 } 155 }
256 156
257 - (remoting::ChromotingClientRuntime*)runtime { 157 - (remoting::ChromotingClientRuntime*)runtime {
258 return remoting::ChromotingClientRuntime::GetInstance(); 158 return remoting::ChromotingClientRuntime::GetInstance();
259 } 159 }
260 160
261 - (void)callbackWithAccessToken: 161 #pragma mark - Implementation
262 (const remoting::OAuthTokenGetter::TokenCallback&)onAccessToken { 162
263 if (_tokenGetter) { 163 - (void)requestHostListFetch {
264 _tokenGetter->CallWithToken(onAccessToken); 164 [_authentication
265 } 165 callbackWithAccessToken:base::BindBlockArc(^(
166 remoting::OAuthTokenGetter::Status status,
167 const std::string& user_email,
168 const std::string& access_token) {
169 NSString* accessToken =
170 [NSString stringWithCString:access_token.c_str()
171 encoding:[NSString defaultCStringEncoding]];
172 [self startHostListFetchWith:accessToken];
173 })];
266 } 174 }
267 175
268 @end 176 @end
OLDNEW
« no previous file with comments | « remoting/client/ios/facade/remoting_service.h ('k') | remoting/client/ios/keychain_wrapper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698