77import android .accounts .Account ;
88import android .app .Activity ;
99import android .content .Intent ;
10+ import com .google .android .gms .auth .GoogleAuthException ;
1011import com .google .android .gms .auth .GoogleAuthUtil ;
1112import com .google .android .gms .auth .UserRecoverableAuthException ;
1213import com .google .android .gms .auth .api .signin .GoogleSignIn ;
2728import io .flutter .plugin .common .MethodChannel .MethodCallHandler ;
2829import io .flutter .plugin .common .MethodChannel .Result ;
2930import io .flutter .plugin .common .PluginRegistry ;
31+ import java .io .IOException ;
3032import java .util .HashMap ;
3133import java .util .List ;
3234import java .util .Map ;
@@ -45,6 +47,7 @@ public class GoogleSignInPlugin implements MethodCallHandler {
4547 private static final String METHOD_SIGN_OUT = "signOut" ;
4648 private static final String METHOD_DISCONNECT = "disconnect" ;
4749 private static final String METHOD_IS_SIGNED_IN = "isSignedIn" ;
50+ private static final String METHOD_CLEAR_AUTH_CACHE = "clearAuthCache" ;
4851
4952 private final IDelegate delegate ;
5053
@@ -86,6 +89,11 @@ public void onMethodCall(MethodCall call, Result result) {
8689 delegate .signOut (result );
8790 break ;
8891
92+ case METHOD_CLEAR_AUTH_CACHE :
93+ String token = call .argument ("token" );
94+ delegate .clearAuthCache (result , token );
95+ break ;
96+
8997 case METHOD_DISCONNECT :
9098 delegate .disconnect (result );
9199 break ;
@@ -130,6 +138,12 @@ public void init(
130138 */
131139 public void getTokens (final Result result , final String email , final boolean shouldRecoverAuth );
132140
141+ /**
142+ * Clears the token from any client cache forcing the next {@link #getTokens} call to fetch a
143+ * new one.
144+ */
145+ public void clearAuthCache (final Result result , final String token );
146+
133147 /**
134148 * Signs the user out. Their credentials may remain valid, meaning they'll be able to silently
135149 * sign back in.
@@ -387,18 +401,15 @@ private static class PendingOperation {
387401 }
388402 }
389403
390- private void recoverAuthFromException (final UserRecoverableAuthException exception ) {
391- registrar
392- .activity ()
393- .runOnUiThread (
394- new Runnable () {
395- @ Override
396- public void run () {
397- registrar
398- .activity ()
399- .startActivityForResult (exception .getIntent (), REQUEST_CODE_RECOVER_AUTH );
400- }
401- });
404+ /** Clears the token kept in the client side cache. */
405+ @ Override
406+ public void clearAuthCache (Result result , String token ) {
407+ try {
408+ GoogleAuthUtil .clearToken (registrar .context (), token );
409+ result .success (null );
410+ } catch (GoogleAuthException | IOException e ) {
411+ result .error (ERROR_REASON_EXCEPTION , e .getMessage (), e );
412+ }
402413 }
403414
404415 /**
@@ -411,8 +422,6 @@ public void run() {
411422 @ Override
412423 public void getTokens (
413424 final Result result , final String email , final boolean shouldRecoverAuth ) {
414- // TODO(issue/11107): Add back the checkAndSetPendingOperation once getTokens is properly
415- // gated from Dart code. Change result.success/error calls below to use finishWith()
416425 if (email == null ) {
417426 result .error (ERROR_REASON_EXCEPTION , "Email is null" , null );
418427 return ;
@@ -428,6 +437,9 @@ public String call() throws Exception {
428437 }
429438 };
430439
440+ // Background task runner has a single thread effectively serializing
441+ // the getToken calls. 1p apps can then enjoy the token cache if multiple
442+ // getToken calls are coming in.
431443 backgroundTaskRunner .runInBackground (
432444 getTokenTask ,
433445 new BackgroundTaskRunner .Callback <String >() {
@@ -440,10 +452,13 @@ public void run(Future<String> tokenFuture) {
440452 result .success (tokenResult );
441453 } catch (ExecutionException e ) {
442454 if (e .getCause () instanceof UserRecoverableAuthException ) {
443- if (shouldRecoverAuth ) {
444- // Move this to top of getTokens method.
455+ if (shouldRecoverAuth && pendingOperation == null ) {
445456 checkAndSetPendingOperation (METHOD_GET_TOKENS , result , email );
446- recoverAuthFromException ((UserRecoverableAuthException ) e .getCause ());
457+ Intent recoveryIntent =
458+ ((UserRecoverableAuthException ) e .getCause ()).getIntent ();
459+ registrar
460+ .activity ()
461+ .startActivityForResult (recoveryIntent , REQUEST_CODE_RECOVER_AUTH );
447462 } else {
448463 result .error (ERROR_USER_RECOVERABLE_AUTH , e .getLocalizedMessage (), null );
449464 }
0 commit comments