OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 #import "ios/chrome/browser/ui/authentication/authentication_flow.h" | 5 #import "ios/chrome/browser/ui/authentication/authentication_flow.h" |
6 | 6 |
7 #include "base/ios/weak_nsobject.h" | |
8 #include "base/logging.h" | 7 #include "base/logging.h" |
9 #include "base/mac/objc_property_releaser.h" | |
10 #include "base/mac/scoped_block.h" | 8 #include "base/mac/scoped_block.h" |
11 #include "base/mac/scoped_nsobject.h" | |
12 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" | 9 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" |
13 #include "ios/chrome/browser/signin/authentication_service.h" | 10 #include "ios/chrome/browser/signin/authentication_service.h" |
14 #include "ios/chrome/browser/signin/authentication_service_factory.h" | 11 #include "ios/chrome/browser/signin/authentication_service_factory.h" |
15 #include "ios/chrome/browser/signin/constants.h" | 12 #include "ios/chrome/browser/signin/constants.h" |
16 #import "ios/chrome/browser/ui/authentication/authentication_flow_performer.h" | 13 #import "ios/chrome/browser/ui/authentication/authentication_flow_performer.h" |
17 #include "ios/chrome/grit/ios_strings.h" | 14 #include "ios/chrome/grit/ios_strings.h" |
18 #import "ios/public/provider/chrome/browser/chrome_browser_provider.h" | 15 #import "ios/public/provider/chrome/browser/chrome_browser_provider.h" |
19 #import "ios/public/provider/chrome/browser/signin/chrome_identity.h" | 16 #import "ios/public/provider/chrome/browser/signin/chrome_identity.h" |
20 #include "ios/public/provider/chrome/browser/signin/chrome_identity_service.h" | 17 #include "ios/public/provider/chrome/browser/signin/chrome_identity_service.h" |
21 #include "ios/public/provider/chrome/browser/signin/signin_error_provider.h" | 18 #include "ios/public/provider/chrome/browser/signin/signin_error_provider.h" |
22 #include "ui/base/l10n/l10n_util.h" | 19 #include "ui/base/l10n/l10n_util.h" |
23 | 20 |
| 21 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 22 #error "This file requires ARC support." |
| 23 #endif |
| 24 |
24 using signin_ui::CompletionCallback; | 25 using signin_ui::CompletionCallback; |
25 | 26 |
26 namespace { | 27 namespace { |
27 | 28 |
28 // The states of the sign-in flow state machine. | 29 // The states of the sign-in flow state machine. |
29 enum AuthenticationState { | 30 enum AuthenticationState { |
30 BEGIN, | 31 BEGIN, |
31 CHECK_SIGNIN_STEPS, | 32 CHECK_SIGNIN_STEPS, |
32 FETCH_MANAGED_STATUS, | 33 FETCH_MANAGED_STATUS, |
33 CHECK_MERGE_CASE, | 34 CHECK_MERGE_CASE, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 - (void)cancelFlow; | 74 - (void)cancelFlow; |
74 | 75 |
75 // Handles an authentication error and show an alert to the user. | 76 // Handles an authentication error and show an alert to the user. |
76 - (void)handleAuthenticationError:(NSError*)error; | 77 - (void)handleAuthenticationError:(NSError*)error; |
77 | 78 |
78 @end | 79 @end |
79 | 80 |
80 @implementation AuthenticationFlow { | 81 @implementation AuthenticationFlow { |
81 ShouldClearData _shouldClearData; | 82 ShouldClearData _shouldClearData; |
82 PostSignInAction _postSignInAction; | 83 PostSignInAction _postSignInAction; |
83 base::scoped_nsobject<UIViewController> _presentingViewController; | 84 UIViewController* _presentingViewController; |
84 base::mac::ScopedBlock<CompletionCallback> _signInCompletion; | 85 CompletionCallback _signInCompletion; |
85 base::scoped_nsobject<AuthenticationFlowPerformer> _performer; | 86 AuthenticationFlowPerformer* _performer; |
86 | 87 |
87 // State machine tracking. | 88 // State machine tracking. |
88 AuthenticationState _state; | 89 AuthenticationState _state; |
89 BOOL _didSignIn; | 90 BOOL _didSignIn; |
90 BOOL _failedOrCancelled; | 91 BOOL _failedOrCancelled; |
91 BOOL _shouldSignIn; | 92 BOOL _shouldSignIn; |
92 BOOL _shouldSignOut; | 93 BOOL _shouldSignOut; |
93 BOOL _shouldShowManagedConfirmation; | 94 BOOL _shouldShowManagedConfirmation; |
94 BOOL _shouldStartSync; | 95 BOOL _shouldStartSync; |
95 ios::ChromeBrowserState* _browserState; | 96 ios::ChromeBrowserState* _browserState; |
96 base::scoped_nsobject<ChromeIdentity> _browserStateIdentity; | 97 ChromeIdentity* _browserStateIdentity; |
97 base::scoped_nsobject<ChromeIdentity> _identityToSignIn; | 98 ChromeIdentity* _identityToSignIn; |
98 base::scoped_nsobject<NSString> _identityToSignInHostedDomain; | 99 NSString* _identityToSignInHostedDomain; |
99 | 100 |
100 // This AuthenticationFlow keeps a reference to |self| while a sign-in flow is | 101 // This AuthenticationFlow keeps a reference to |self| while a sign-in flow is |
101 // is in progress to ensure it outlives any attempt to destroy it in | 102 // is in progress to ensure it outlives any attempt to destroy it in |
102 // |_signInCompletion|. | 103 // |_signInCompletion|. |
103 base::scoped_nsobject<AuthenticationFlow> _selfRetainer; | 104 AuthenticationFlow* _selfRetainer; |
104 | |
105 base::mac::ObjCPropertyReleaser _propertyReleaser_AuthenticationFlow; | |
106 } | 105 } |
107 | 106 |
108 @synthesize handlingError = _handlingError; | 107 @synthesize handlingError = _handlingError; |
109 | 108 |
110 #pragma mark - Public methods | 109 #pragma mark - Public methods |
111 | 110 |
112 - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState | 111 - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState |
113 identity:(ChromeIdentity*)identity | 112 identity:(ChromeIdentity*)identity |
114 shouldClearData:(ShouldClearData)shouldClearData | 113 shouldClearData:(ShouldClearData)shouldClearData |
115 postSignInAction:(PostSignInAction)postSignInAction | 114 postSignInAction:(PostSignInAction)postSignInAction |
116 presentingViewController: | 115 presentingViewController: |
117 (UIViewController*)presentingViewController { | 116 (UIViewController*)presentingViewController { |
118 if ((self = [super init])) { | 117 if ((self = [super init])) { |
119 DCHECK(browserState); | 118 DCHECK(browserState); |
120 DCHECK(presentingViewController); | 119 DCHECK(presentingViewController); |
121 _browserState = browserState; | 120 _browserState = browserState; |
122 _identityToSignIn.reset([identity retain]); | 121 _identityToSignIn = identity; |
123 _shouldClearData = shouldClearData; | 122 _shouldClearData = shouldClearData; |
124 _postSignInAction = postSignInAction; | 123 _postSignInAction = postSignInAction; |
125 _presentingViewController.reset([presentingViewController retain]); | 124 _presentingViewController = presentingViewController; |
126 _state = BEGIN; | 125 _state = BEGIN; |
127 _propertyReleaser_AuthenticationFlow.Init(self, [AuthenticationFlow class]); | |
128 } | 126 } |
129 return self; | 127 return self; |
130 } | 128 } |
131 | 129 |
132 - (void)startSignInWithCompletion:(CompletionCallback)completion { | 130 - (void)startSignInWithCompletion:(CompletionCallback)completion { |
133 DCHECK_EQ(BEGIN, _state); | 131 DCHECK_EQ(BEGIN, _state); |
134 DCHECK(!_signInCompletion); | 132 DCHECK(!_signInCompletion); |
135 DCHECK(completion); | 133 DCHECK(completion); |
136 _signInCompletion.reset(completion, base::scoped_policy::RETAIN); | 134 _signInCompletion = [completion copy]; |
137 _selfRetainer.reset([self retain]); | 135 _selfRetainer = self; |
138 // Kick off the state machine. | 136 // Kick off the state machine. |
139 if (!_performer) { | 137 if (!_performer) { |
140 _performer.reset( | 138 _performer = [[AuthenticationFlowPerformer alloc] initWithDelegate:self]; |
141 [[AuthenticationFlowPerformer alloc] initWithDelegate:self]); | |
142 } | 139 } |
143 [self continueSignin]; | 140 [self continueSignin]; |
144 } | 141 } |
145 | 142 |
146 - (void)cancelAndDismiss { | 143 - (void)cancelAndDismiss { |
147 if (_state == DONE) | 144 if (_state == DONE) |
148 return; | 145 return; |
149 | 146 |
150 [_performer cancelAndDismiss]; | 147 [_performer cancelAndDismiss]; |
151 if (_state != DONE) { | 148 if (_state != DONE) { |
152 // The performer might not have been able to continue the flow if it was | 149 // The performer might not have been able to continue the flow if it was |
153 // waiting for a callback (e.g. waiting for AccountReconcilor). In this | 150 // waiting for a callback (e.g. waiting for AccountReconcilor). In this |
154 // case, we force the flow to finish synchronously. | 151 // case, we force the flow to finish synchronously. |
155 [self cancelFlow]; | 152 [self cancelFlow]; |
156 } | 153 } |
157 | 154 |
158 DCHECK_EQ(DONE, _state); | 155 DCHECK_EQ(DONE, _state); |
159 } | 156 } |
160 | 157 |
161 - (void)setPresentingViewController: | 158 - (void)setPresentingViewController: |
162 (UIViewController*)presentingViewController { | 159 (UIViewController*)presentingViewController { |
163 _presentingViewController.reset([presentingViewController retain]); | 160 _presentingViewController = presentingViewController; |
164 } | 161 } |
165 | 162 |
166 #pragma mark State machine management | 163 #pragma mark State machine management |
167 | 164 |
168 - (AuthenticationState)nextStateFailedOrCancelled { | 165 - (AuthenticationState)nextStateFailedOrCancelled { |
169 DCHECK(_failedOrCancelled); | 166 DCHECK(_failedOrCancelled); |
170 switch (_state) { | 167 switch (_state) { |
171 case BEGIN: | 168 case BEGIN: |
172 case CHECK_SIGNIN_STEPS: | 169 case CHECK_SIGNIN_STEPS: |
173 case FETCH_MANAGED_STATUS: | 170 case FETCH_MANAGED_STATUS: |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 | 305 |
309 case COMPLETE_WITH_FAILURE: | 306 case COMPLETE_WITH_FAILURE: |
310 if (_didSignIn) { | 307 if (_didSignIn) { |
311 [_performer signOutImmediatelyFromBrowserState:_browserState]; | 308 [_performer signOutImmediatelyFromBrowserState:_browserState]; |
312 // Enabling/disabling sync does not take effect in the sync backend | 309 // Enabling/disabling sync does not take effect in the sync backend |
313 // until committing changes. | 310 // until committing changes. |
314 [_performer commitSyncForBrowserState:_browserState]; | 311 [_performer commitSyncForBrowserState:_browserState]; |
315 } | 312 } |
316 [self completeSignInWithSuccess:NO]; | 313 [self completeSignInWithSuccess:NO]; |
317 return; | 314 return; |
318 case CLEANUP_BEFORE_DONE: | 315 case CLEANUP_BEFORE_DONE: { |
319 // Clean up asynchronously to ensure that |self| does not die while | 316 // Clean up asynchronously to ensure that |self| does not die while |
320 // the flow is running. | 317 // the flow is running. |
321 DCHECK([NSThread isMainThread]); | 318 DCHECK([NSThread isMainThread]); |
322 dispatch_async(dispatch_get_main_queue(), ^{ | 319 dispatch_async(dispatch_get_main_queue(), ^{ |
323 _selfRetainer.reset(); | 320 _selfRetainer = nil; |
324 }); | 321 }); |
325 [self continueSignin]; | 322 [self continueSignin]; |
326 return; | 323 return; |
| 324 } |
327 case DONE: | 325 case DONE: |
328 return; | 326 return; |
329 } | 327 } |
330 NOTREACHED(); | 328 NOTREACHED(); |
331 } | 329 } |
332 | 330 |
333 - (void)checkSigninSteps { | 331 - (void)checkSigninSteps { |
334 _browserStateIdentity.reset( | 332 _browserStateIdentity = |
335 [AuthenticationServiceFactory::GetForBrowserState(_browserState) | 333 AuthenticationServiceFactory::GetForBrowserState(_browserState) |
336 ->GetAuthenticatedIdentity() retain]); | 334 ->GetAuthenticatedIdentity(); |
337 if (_browserStateIdentity) | 335 if (_browserStateIdentity) |
338 _shouldSignOut = YES; | 336 _shouldSignOut = YES; |
339 | 337 |
340 _shouldSignIn = YES; | 338 _shouldSignIn = YES; |
341 _shouldStartSync = _postSignInAction == POST_SIGNIN_ACTION_START_SYNC; | 339 _shouldStartSync = _postSignInAction == POST_SIGNIN_ACTION_START_SYNC; |
342 } | 340 } |
343 | 341 |
344 - (void)signInIdentity:(ChromeIdentity*)identity { | 342 - (void)signInIdentity:(ChromeIdentity*)identity { |
345 if (ios::GetChromeBrowserProvider() | 343 if (ios::GetChromeBrowserProvider() |
346 ->GetChromeIdentityService() | 344 ->GetChromeIdentityService() |
347 ->IsValidIdentity(identity)) { | 345 ->IsValidIdentity(identity)) { |
348 [_performer signInIdentity:identity | 346 [_performer signInIdentity:identity |
349 withHostedDomain:_identityToSignInHostedDomain | 347 withHostedDomain:_identityToSignInHostedDomain |
350 toBrowserState:_browserState]; | 348 toBrowserState:_browserState]; |
351 _didSignIn = YES; | 349 _didSignIn = YES; |
352 [self continueSignin]; | 350 [self continueSignin]; |
353 } else { | 351 } else { |
354 // Handle the case where the identity is no longer valid. | 352 // Handle the case where the identity is no longer valid. |
355 [self handleAuthenticationError:IdentityMissingError()]; | 353 [self handleAuthenticationError:IdentityMissingError()]; |
356 } | 354 } |
357 } | 355 } |
358 | 356 |
359 - (void)completeSignInWithSuccess:(BOOL)success { | 357 - (void)completeSignInWithSuccess:(BOOL)success { |
360 DCHECK(_signInCompletion) | 358 DCHECK(_signInCompletion) |
361 << "|completeSignInWithSuccess| should not be called twice."; | 359 << "|completeSignInWithSuccess| should not be called twice."; |
362 _signInCompletion.get()(success); | 360 _signInCompletion(success); |
363 _signInCompletion.reset(); | 361 _signInCompletion = nil; |
364 [self continueSignin]; | 362 [self continueSignin]; |
365 } | 363 } |
366 | 364 |
367 - (void)cancelFlow { | 365 - (void)cancelFlow { |
368 if (_failedOrCancelled) { | 366 if (_failedOrCancelled) { |
369 // Avoid double handling of cancel or error. | 367 // Avoid double handling of cancel or error. |
370 return; | 368 return; |
371 } | 369 } |
372 _failedOrCancelled = YES; | 370 _failedOrCancelled = YES; |
373 [self continueSignin]; | 371 [self continueSignin]; |
374 } | 372 } |
375 | 373 |
376 - (void)handleAuthenticationError:(NSError*)error { | 374 - (void)handleAuthenticationError:(NSError*)error { |
377 if (_failedOrCancelled) { | 375 if (_failedOrCancelled) { |
378 // Avoid double handling of cancel or error. | 376 // Avoid double handling of cancel or error. |
379 return; | 377 return; |
380 } | 378 } |
381 DCHECK(error); | 379 DCHECK(error); |
382 _failedOrCancelled = YES; | 380 _failedOrCancelled = YES; |
383 self.handlingError = YES; | 381 self.handlingError = YES; |
384 base::WeakNSObject<AuthenticationFlow> weakSelf(self); | 382 __weak AuthenticationFlow* weakSelf = self; |
385 [_performer showAuthenticationError:error | 383 [_performer showAuthenticationError:error |
386 withCompletion:^{ | 384 withCompletion:^{ |
387 base::scoped_nsobject<AuthenticationFlow> strongSelf( | 385 AuthenticationFlow* strongSelf = weakSelf; |
388 [weakSelf retain]); | |
389 if (!strongSelf) | 386 if (!strongSelf) |
390 return; | 387 return; |
391 [strongSelf setHandlingError:NO]; | 388 [strongSelf setHandlingError:NO]; |
392 [strongSelf continueSignin]; | 389 [strongSelf continueSignin]; |
393 } | 390 } |
394 viewController:_presentingViewController]; | 391 viewController:_presentingViewController]; |
395 } | 392 } |
396 | 393 |
397 #pragma mark AuthenticationFlowPerformerDelegate | 394 #pragma mark AuthenticationFlowPerformerDelegate |
398 | 395 |
(...skipping 12 matching lines...) Expand all Loading... |
411 [self continueSignin]; | 408 [self continueSignin]; |
412 } | 409 } |
413 | 410 |
414 - (void)didChooseCancel { | 411 - (void)didChooseCancel { |
415 [self cancelFlow]; | 412 [self cancelFlow]; |
416 } | 413 } |
417 | 414 |
418 - (void)didFetchManagedStatus:(NSString*)hostedDomain { | 415 - (void)didFetchManagedStatus:(NSString*)hostedDomain { |
419 DCHECK_EQ(FETCH_MANAGED_STATUS, _state); | 416 DCHECK_EQ(FETCH_MANAGED_STATUS, _state); |
420 _shouldShowManagedConfirmation = [hostedDomain length] > 0; | 417 _shouldShowManagedConfirmation = [hostedDomain length] > 0; |
421 _identityToSignInHostedDomain.reset([hostedDomain retain]); | 418 _identityToSignInHostedDomain = hostedDomain; |
422 [self continueSignin]; | 419 [self continueSignin]; |
423 } | 420 } |
424 | 421 |
425 - (void)didFailFetchManagedStatus:(NSError*)error { | 422 - (void)didFailFetchManagedStatus:(NSError*)error { |
426 DCHECK_EQ(FETCH_MANAGED_STATUS, _state); | 423 DCHECK_EQ(FETCH_MANAGED_STATUS, _state); |
427 NSError* flowError = | 424 NSError* flowError = |
428 [NSError errorWithDomain:kAuthenticationErrorDomain | 425 [NSError errorWithDomain:kAuthenticationErrorDomain |
429 code:AUTHENTICATION_FLOW_ERROR | 426 code:AUTHENTICATION_FLOW_ERROR |
430 userInfo:@{ | 427 userInfo:@{ |
431 NSLocalizedDescriptionKey : | 428 NSLocalizedDescriptionKey : |
(...skipping 11 matching lines...) Expand all Loading... |
443 [self cancelFlow]; | 440 [self cancelFlow]; |
444 } | 441 } |
445 | 442 |
446 - (UIViewController*)presentingViewController { | 443 - (UIViewController*)presentingViewController { |
447 return _presentingViewController; | 444 return _presentingViewController; |
448 } | 445 } |
449 | 446 |
450 #pragma mark - Used for testing | 447 #pragma mark - Used for testing |
451 | 448 |
452 - (void)setPerformerForTesting:(AuthenticationFlowPerformer*)performer { | 449 - (void)setPerformerForTesting:(AuthenticationFlowPerformer*)performer { |
453 _performer.reset([performer retain]); | 450 _performer = performer; |
454 } | 451 } |
455 | 452 |
456 @end | 453 @end |
OLD | NEW |