Commit 18bee31e authored by Alice Wang's avatar Alice Wang Committed by Commit Bot

[Android][WebSignin] Improve sign-in error retry flow

This CL improves the sign-in error retry flow by adding a sign-in state
check before signing in and keep WebSigninBridge when there is a
sign-in error.

Bug: 1133704
Change-Id: Id4c1bba4f5af997ccfeb43972ba622eb5268d823
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2440582Reviewed-by: default avatarBoris Sazonov <bsazonov@chromium.org>
Commit-Queue: Alice Wang <aliceywang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#812672}
parent 7308d741
...@@ -24,6 +24,9 @@ import org.chromium.components.signin.AccountManagerFacadeProvider; ...@@ -24,6 +24,9 @@ import org.chromium.components.signin.AccountManagerFacadeProvider;
import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.AccountUtils;
import org.chromium.components.signin.base.CoreAccountInfo; import org.chromium.components.signin.base.CoreAccountInfo;
import org.chromium.components.signin.base.GoogleServiceAuthError; import org.chromium.components.signin.base.GoogleServiceAuthError;
import org.chromium.components.signin.identitymanager.ConsentLevel;
import org.chromium.components.signin.identitymanager.IdentityManager;
import org.chromium.components.signin.metrics.SignoutReason;
import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.base.WindowAndroid;
...@@ -40,6 +43,7 @@ public class AccountPickerDelegate implements WebSigninBridge.Listener { ...@@ -40,6 +43,7 @@ public class AccountPickerDelegate implements WebSigninBridge.Listener {
private final WebSigninBridge.Factory mWebSigninBridgeFactory; private final WebSigninBridge.Factory mWebSigninBridgeFactory;
private final String mContinueUrl; private final String mContinueUrl;
private final SigninManager mSigninManager; private final SigninManager mSigninManager;
private final IdentityManager mIdentityManager;
private @Nullable WebSigninBridge mWebSigninBridge; private @Nullable WebSigninBridge mWebSigninBridge;
private Callback<GoogleServiceAuthError> mOnSignInErrorCallback; private Callback<GoogleServiceAuthError> mOnSignInErrorCallback;
...@@ -60,6 +64,8 @@ public class AccountPickerDelegate implements WebSigninBridge.Listener { ...@@ -60,6 +64,8 @@ public class AccountPickerDelegate implements WebSigninBridge.Listener {
mContinueUrl = continueUrl; mContinueUrl = continueUrl;
mSigninManager = IdentityServicesProvider.get().getSigninManager( mSigninManager = IdentityServicesProvider.get().getSigninManager(
Profile.getLastUsedRegularProfile()); Profile.getLastUsedRegularProfile());
mIdentityManager = IdentityServicesProvider.get().getIdentityManager(
Profile.getLastUsedRegularProfile());
} }
/** /**
...@@ -75,6 +81,14 @@ public class AccountPickerDelegate implements WebSigninBridge.Listener { ...@@ -75,6 +81,14 @@ public class AccountPickerDelegate implements WebSigninBridge.Listener {
*/ */
public void signIn(CoreAccountInfo coreAccountInfo, public void signIn(CoreAccountInfo coreAccountInfo,
Callback<GoogleServiceAuthError> onSignInErrorCallback) { Callback<GoogleServiceAuthError> onSignInErrorCallback) {
if (mIdentityManager.getPrimaryAccountInfo(ConsentLevel.NOT_REQUIRED) != null) {
// In case an error is fired because cookies are taking longer to generate than usual,
// if user retries the sign-in from the error screen, we need to sign out the user
// first before signing in again.
destroyWebSigninBridge();
// TODO(https://crbug.com/1133752): Revise sign-out reason
mSigninManager.signOut(SignoutReason.ABORT_SIGNIN);
}
mOnSignInErrorCallback = onSignInErrorCallback; mOnSignInErrorCallback = onSignInErrorCallback;
mWebSigninBridge = mWebSigninBridgeFactory.create( mWebSigninBridge = mWebSigninBridgeFactory.create(
Profile.getLastUsedRegularProfile(), coreAccountInfo, this); Profile.getLastUsedRegularProfile(), coreAccountInfo, this);
...@@ -152,7 +166,6 @@ public class AccountPickerDelegate implements WebSigninBridge.Listener { ...@@ -152,7 +166,6 @@ public class AccountPickerDelegate implements WebSigninBridge.Listener {
public void onSigninFailed(GoogleServiceAuthError error) { public void onSigninFailed(GoogleServiceAuthError error) {
ThreadUtils.assertOnUiThread(); ThreadUtils.assertOnUiThread();
mOnSignInErrorCallback.onResult(error); mOnSignInErrorCallback.onResult(error);
destroyWebSigninBridge();
} }
/** /**
......
...@@ -5,10 +5,12 @@ ...@@ -5,10 +5,12 @@
package org.chromium.chrome.browser.signin.account_picker; package org.chromium.chrome.browser.signin.account_picker;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
...@@ -72,6 +74,9 @@ public class AccountPickerDelegateTest { ...@@ -72,6 +74,9 @@ public class AccountPickerDelegateTest {
@Mock @Mock
private SigninManager mSigninManagerMock; private SigninManager mSigninManagerMock;
@Mock
private IdentityManager mIdentityManagerMock;
@Mock @Mock
private Profile mProfileMock; private Profile mProfileMock;
...@@ -88,9 +93,6 @@ public class AccountPickerDelegateTest { ...@@ -88,9 +93,6 @@ public class AccountPickerDelegateTest {
private AccountPickerDelegate mDelegate; private AccountPickerDelegate mDelegate;
private final IdentityManager mIdentityManager =
new IdentityManager(/* nativeIdentityManager= */ 0, /* OAuth2TokenService= */ null);
@Before @Before
public void setUp() { public void setUp() {
initMocks(this); initMocks(this);
...@@ -99,7 +101,8 @@ public class AccountPickerDelegateTest { ...@@ -99,7 +101,8 @@ public class AccountPickerDelegateTest {
Profile.setLastUsedProfileForTesting(mProfileMock); Profile.setLastUsedProfileForTesting(mProfileMock);
IdentityServicesProvider.setInstanceForTests(mock(IdentityServicesProvider.class)); IdentityServicesProvider.setInstanceForTests(mock(IdentityServicesProvider.class));
when(IdentityServicesProvider.get().getIdentityManager(any())).thenReturn(mIdentityManager); when(IdentityServicesProvider.get().getIdentityManager(any()))
.thenReturn(mIdentityManagerMock);
when(IdentityServicesProvider.get().getSigninManager(any())).thenReturn(mSigninManagerMock); when(IdentityServicesProvider.get().getSigninManager(any())).thenReturn(mSigninManagerMock);
mDelegate = new AccountPickerDelegate( mDelegate = new AccountPickerDelegate(
...@@ -145,6 +148,27 @@ public class AccountPickerDelegateTest { ...@@ -145,6 +148,27 @@ public class AccountPickerDelegateTest {
verify(mWebSigninBridgeMock).destroy(); verify(mWebSigninBridgeMock).destroy();
} }
@Test
public void testSigninTriggersSignoutIfAlreadySignedIn() {
// In case an error is fired because cookies are taking longer to generate than usual,
// if user retries the sign-in from the error screen, we need to sign out the user
// first before signing in again.
Account account =
mAccountManagerTestRule.addAccount(AccountManagerTestRule.TEST_ACCOUNT_EMAIL);
CoreAccountInfo coreAccountInfo = mAccountManagerTestRule.toCoreAccountInfo(account.name);
mDelegate.signIn(coreAccountInfo, error -> {});
when(mIdentityManagerMock.getPrimaryAccountInfo(anyInt())).thenReturn(coreAccountInfo);
mDelegate.signIn(coreAccountInfo, error -> {});
InOrder calledInOrder = inOrder(mWebSigninBridgeMock, mSigninManagerMock,
mWebSigninBridgeFactoryMock, mSigninManagerMock);
calledInOrder.verify(mWebSigninBridgeMock).destroy();
calledInOrder.verify(mSigninManagerMock).signOut(anyInt());
calledInOrder.verify(mWebSigninBridgeFactoryMock)
.create(mProfileMock, coreAccountInfo, mDelegate);
calledInOrder.verify(mSigninManagerMock).signin(eq(coreAccountInfo), any());
}
@Test @Test
public void testSignInFailedWithConnectionError() { public void testSignInFailedWithConnectionError() {
Account account = Account account =
...@@ -155,7 +179,9 @@ public class AccountPickerDelegateTest { ...@@ -155,7 +179,9 @@ public class AccountPickerDelegateTest {
mDelegate.signIn(coreAccountInfo, mockCallback); mDelegate.signIn(coreAccountInfo, mockCallback);
mDelegate.onSigninFailed(error); mDelegate.onSigninFailed(error);
verify(mockCallback).onResult(error); verify(mockCallback).onResult(error);
verify(mWebSigninBridgeMock).destroy(); // WebSigninBridge should be kept alive in case cookies are taking longer to
// generate than usual
verify(mWebSigninBridgeMock, never()).destroy();
} }
@Test @Test
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment