This repository was archived by the owner on Feb 22, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[google_sign_in] Fix chained async methods in error handling zones #2059
Merged
Merged
Changes from 3 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
bec84c1
[google_sign_in] Fix chained async methods in error handling zones
mehmetf 21ccfcb
Make analyzer happy. Swich to real Exception object.
mehmetf 650e69f
Update CHANGELOG.md
collinjackson 398abda
Review comments
mehmetf 72dc483
Merge branch 'b3' of github.com:mehmetf/plugins into b3
mehmetf File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -230,50 +230,57 @@ class GoogleSignIn { | |||||
| } | ||||||
|
|
||||||
| Future<void> _ensureInitialized() { | ||||||
| if (_initialization == null) { | ||||||
| _initialization = channel.invokeMethod<void>('init', <String, dynamic>{ | ||||||
| 'signInOption': (signInOption ?? SignInOption.standard).toString(), | ||||||
| 'scopes': scopes ?? <String>[], | ||||||
| 'hostedDomain': hostedDomain, | ||||||
| }) | ||||||
| ..catchError((dynamic _) { | ||||||
| // Invalidate initialization if it errored out. | ||||||
| _initialization = null; | ||||||
| }); | ||||||
| } | ||||||
| return _initialization; | ||||||
| return _initialization ??= | ||||||
| channel.invokeMethod<void>('init', <String, dynamic>{ | ||||||
| 'signInOption': (signInOption ?? SignInOption.standard).toString(), | ||||||
| 'scopes': scopes ?? <String>[], | ||||||
| 'hostedDomain': hostedDomain, | ||||||
| }) | ||||||
| ..catchError((dynamic _) { | ||||||
| // Invalidate initialization if it errored out. | ||||||
| _initialization = null; | ||||||
| }); | ||||||
| } | ||||||
|
|
||||||
| /// Keeps track of the most recently scheduled method call. | ||||||
| _MethodCompleter _lastMethodCompleter; | ||||||
| /// The most recently scheduled method call. | ||||||
| Future<void> _lastMethodCall; | ||||||
|
|
||||||
| /// Returns a [Future] that completes with a success after [future], whether | ||||||
| /// it completed with a value or an error. | ||||||
| Future<void> _waitFor(Future<void> future) { | ||||||
| final Completer<void> completer = Completer<void>(); | ||||||
| future.whenComplete(completer.complete).catchError((dynamic _) { | ||||||
| // Ignore if previous call completed with an error. | ||||||
| }); | ||||||
| return completer.future; | ||||||
| } | ||||||
|
|
||||||
| /// Adds call to [method] in a queue for execution. | ||||||
| /// | ||||||
| /// At most one in flight call is allowed to prevent concurrent (out of order) | ||||||
| /// updates to [currentUser] and [onCurrentUserChanged]. | ||||||
| Future<GoogleSignInAccount> _addMethodCall(String method) { | ||||||
| if (_lastMethodCompleter == null) { | ||||||
| _lastMethodCompleter = _MethodCompleter(method) | ||||||
| ..complete(_callMethod(method)); | ||||||
| return _lastMethodCompleter.future; | ||||||
| Future<GoogleSignInAccount> _addMethodCall(String method) async { | ||||||
| Future<GoogleSignInAccount> response; | ||||||
| if (_lastMethodCall == null) { | ||||||
| response = _callMethod(method); | ||||||
| } else { | ||||||
| response = _lastMethodCall.then((_) { | ||||||
| // If after the last completed call currentUser is not null and requested | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| // method is a sign in method, re-use the same authenticated user | ||||||
| // instead of making extra call to the native side. | ||||||
| const List<String> kSignInMethods = <String>[ | ||||||
| 'signIn', | ||||||
| 'signInSilently' | ||||||
| ]; | ||||||
| if (kSignInMethods.contains(method) && _currentUser != null) { | ||||||
| return _currentUser; | ||||||
| } else { | ||||||
| return _callMethod(method); | ||||||
| } | ||||||
| }); | ||||||
| } | ||||||
|
|
||||||
| final _MethodCompleter completer = _MethodCompleter(method); | ||||||
| _lastMethodCompleter.future.whenComplete(() { | ||||||
| // If after the last completed call currentUser is not null and requested | ||||||
| // method is a sign in method, re-use the same authenticated user | ||||||
| // instead of making extra call to the native side. | ||||||
| const List<String> kSignInMethods = <String>['signIn', 'signInSilently']; | ||||||
| if (kSignInMethods.contains(method) && _currentUser != null) { | ||||||
| completer.complete(_currentUser); | ||||||
| } else { | ||||||
| completer.complete(_callMethod(method)); | ||||||
| } | ||||||
| }).catchError((dynamic _) { | ||||||
| // Ignore if previous call completed with an error. | ||||||
| }); | ||||||
| _lastMethodCompleter = completer; | ||||||
| return _lastMethodCompleter.future; | ||||||
| _lastMethodCall = _waitFor(response); | ||||||
| return response; | ||||||
| } | ||||||
|
|
||||||
| /// The currently signed in account, or null if the user is signed out. | ||||||
|
|
@@ -296,12 +303,17 @@ class GoogleSignIn { | |||||
| /// returned Future completes with [PlatformException] whose `code` can be | ||||||
| /// either [kSignInRequiredError] (when there is no authenticated user) or | ||||||
| /// [kSignInFailedError] (when an unknown error occurred). | ||||||
| Future<GoogleSignInAccount> signInSilently({bool suppressErrors = true}) { | ||||||
| final Future<GoogleSignInAccount> result = _addMethodCall('signInSilently'); | ||||||
| if (suppressErrors) { | ||||||
| return result.catchError((dynamic _) => null); | ||||||
| Future<GoogleSignInAccount> signInSilently( | ||||||
| {bool suppressErrors = true}) async { | ||||||
| try { | ||||||
| return await _addMethodCall('signInSilently'); | ||||||
| } catch (_) { | ||||||
| if (suppressErrors) { | ||||||
| return null; | ||||||
| } else { | ||||||
| rethrow; | ||||||
| } | ||||||
| } | ||||||
| return result; | ||||||
| } | ||||||
|
|
||||||
| /// Returns a future that resolves to whether a user is currently signed in. | ||||||
|
|
@@ -334,26 +346,3 @@ class GoogleSignIn { | |||||
| /// authentication. | ||||||
| Future<GoogleSignInAccount> disconnect() => _addMethodCall('disconnect'); | ||||||
| } | ||||||
|
|
||||||
| class _MethodCompleter { | ||||||
| _MethodCompleter(this.method); | ||||||
|
|
||||||
| final String method; | ||||||
| final Completer<GoogleSignInAccount> _completer = | ||||||
| Completer<GoogleSignInAccount>(); | ||||||
|
|
||||||
| Future<void> complete(FutureOr<GoogleSignInAccount> value) async { | ||||||
| if (value is Future<GoogleSignInAccount>) { | ||||||
| try { | ||||||
| _completer.complete(await value); | ||||||
| } catch (e, stacktrace) { | ||||||
| _completer.completeError(e, stacktrace); | ||||||
| } | ||||||
| } else { | ||||||
| _completer.complete(value); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| bool get isCompleted => _completer.isCompleted; | ||||||
| Future<GoogleSignInAccount> get future => _completer.future; | ||||||
| } | ||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I would probably make this
staticif it doesn't access any data from the class.