// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.password_manager;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.chromium.chrome.browser.password_manager.PasswordManagerHelper.START_PASSWORDS_EXPORT;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.common.api.Status;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowLooper;
import org.robolectric.shadows.ShadowSystemClock;
import org.chromium.base.Callback;
import org.chromium.base.CollectionUtil;
import org.chromium.base.ContextUtils;
import org.chromium.base.supplier.ObservableSupplier;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.Batch;
import org.chromium.base.test.util.Features.DisableFeatures;
import org.chromium.base.test.util.Features.EnableFeatures;
import org.chromium.base.test.util.HistogramWatcher;
import org.chromium.base.test.util.JniMocker;
import org.chromium.chrome.browser.access_loss.PasswordAccessLossWarningType;
import org.chromium.chrome.browser.access_loss.R;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.loading_modal.LoadingModalDialogCoordinator;
import org.chromium.chrome.browser.password_manager.CredentialManagerLauncher.CredentialManagerBackendException;
import org.chromium.chrome.browser.password_manager.CredentialManagerLauncher.CredentialManagerError;
import org.chromium.chrome.browser.password_manager.PasswordCheckupClientHelper.PasswordCheckBackendException;
import org.chromium.chrome.browser.password_manager.PasswordManagerHelper.PasswordCheckOperation;
import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.settings.SettingsLauncherFactory;
import org.chromium.chrome.browser.sync.SyncServiceFactory;
import org.chromium.components.browser_ui.settings.SettingsLauncher;
import org.chromium.components.browser_ui.settings.SettingsLauncher.SettingsFragment;
import org.chromium.components.prefs.PrefService;
import org.chromium.components.signin.base.CoreAccountInfo;
import org.chromium.components.signin.base.GoogleServiceAuthError;
import org.chromium.components.signin.base.GoogleServiceAuthError.State;
import org.chromium.components.sync.DataType;
import org.chromium.components.sync.SyncService;
import org.chromium.components.sync.UserSelectableType;
import org.chromium.components.user_prefs.UserPrefs;
import org.chromium.components.user_prefs.UserPrefsJni;
import org.chromium.ui.modaldialog.ModalDialogManager;
import org.chromium.ui.modaldialog.ModalDialogProperties;
import org.chromium.ui.modelutil.PropertyModel;
import java.util.HashSet;
import java.util.Optional;
import java.util.OptionalInt;
/** Tests for password manager helper methods. */
@RunWith(BaseRobolectricTestRunner.class)
@Config(
manifest = Config.NONE,
shadows = {ShadowSystemClock.class})
@Batch(Batch.PER_CLASS)
@DisableFeatures(
ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_LOCAL_PASSWORDS_ANDROID_ACCESS_LOSS_WARNING)
public class PasswordManagerHelperTest {
private static final String TEST_EMAIL_ADDRESS = "[email protected]";
private static final String TEST_NO_EMAIL_ADDRESS = null;
@Rule public JniMocker mJniMocker = new JniMocker();
// TODO(crbug.com/40854050): Use fakes for CredentialManagerLauncher,
// PasswordCheckupClientHelper
// and corresponding factories
@Mock private PasswordCheckupClientHelperFactory mPasswordCheckupClientHelperFactoryMock;
@Mock private CredentialManagerLauncherFactory mCredentialManagerLauncherFactoryMock;
@Mock private CredentialManagerLauncher mCredentialManagerLauncherMock;
@Mock private PasswordCheckupClientHelper mPasswordCheckupClientHelperMock;
@Mock private Profile mProfile;
@Mock private PrefService mPrefService;
@Mock private UserPrefs.Natives mUserPrefsJniMock;
@Mock private PasswordManagerUtilBridge.Natives mPasswordManagerUtilBridgeJniMock;
@Mock private SyncService mSyncServiceMock;
@Mock private SettingsLauncher mSettingsLauncherMock;
@Mock private PendingIntent mPendingIntentMock;
@Mock private ObservableSupplier<ModalDialogManager> mModalDialogManagerSupplier;
// TODO(crbug.com/40854050): Use fake instead of mock
@Mock private PasswordManagerBackendSupportHelper mBackendSupportHelperMock;
private ModalDialogManager mModalDialogManager;
@Mock LoadingModalDialogCoordinator mLoadingModalDialogCoordinator;
private LoadingModalDialogCoordinator.Observer mLoadingDialogCoordinatorObserver;
private PasswordManagerHelper mPasswordManagerHelper;
@Before
public void setUp() throws PasswordCheckBackendException, CredentialManagerBackendException {
// TODO(crbug.com/41483830): Parametrize the tests for account and local storage.
// TODO(crbug.com/40940922): Parametrise the tests for local and account.
MockitoAnnotations.initMocks(this);
mJniMocker.mock(UserPrefsJni.TEST_HOOKS, mUserPrefsJniMock);
mJniMocker.mock(PasswordManagerUtilBridgeJni.TEST_HOOKS, mPasswordManagerUtilBridgeJniMock);
mPasswordManagerHelper = new PasswordManagerHelper(mProfile);
when(mUserPrefsJniMock.get(mProfile)).thenReturn(mPrefService);
when(mPrefService.getBoolean(Pref.UNENROLLED_FROM_GOOGLE_MOBILE_SERVICES_DUE_TO_ERRORS))
.thenReturn(false);
SyncServiceFactory.setInstanceForTesting(mSyncServiceMock);
when(mSyncServiceMock.isEngineInitialized()).thenReturn(true);
when(mSyncServiceMock.getAuthError()).thenReturn(GoogleServiceAuthError.State.NONE);
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.PENDING);
mModalDialogManager =
new ModalDialogManager(
mock(ModalDialogManager.Presenter.class),
ModalDialogManager.ModalDialogType.APP);
when(mModalDialogManagerSupplier.get()).thenReturn(mModalDialogManager);
doAnswer(
invocation -> {
mLoadingDialogCoordinatorObserver = invocation.getArgument(0);
return null;
})
.when(mLoadingModalDialogCoordinator)
.addObserver(any(LoadingModalDialogCoordinator.Observer.class));
PasswordManagerBackendSupportHelper.setInstanceForTesting(mBackendSupportHelperMock);
when(mBackendSupportHelperMock.isBackendPresent()).thenReturn(true);
when(mPasswordManagerUtilBridgeJniMock.areMinUpmRequirementsMet()).thenReturn(true);
when(mPasswordCheckupClientHelperFactoryMock.createHelper())
.thenReturn(mPasswordCheckupClientHelperMock);
PasswordCheckupClientHelperFactory.setFactoryForTesting(
mPasswordCheckupClientHelperFactoryMock);
when(mCredentialManagerLauncherFactoryMock.createLauncher())
.thenReturn(mCredentialManagerLauncherMock);
CredentialManagerLauncherFactory.setFactoryForTesting(
mCredentialManagerLauncherFactoryMock);
SettingsLauncherFactory.setInstanceForTesting(mSettingsLauncherMock);
}
@Test
public void testSyncCheckNoSyncConsent() {
when(mSyncServiceMock.hasSyncConsent()).thenReturn(false);
assertFalse(
PasswordManagerHelper.isSyncingPasswordsWithNoCustomPassphrase(mSyncServiceMock));
}
@Test
public void testActivelySyncingPasswordsWithNoCustomPassphrase() {
when(mSyncServiceMock.hasSyncConsent()).thenReturn(true);
when(mSyncServiceMock.getActiveDataTypes())
.thenReturn(CollectionUtil.newHashSet(DataType.PASSWORDS));
when(mSyncServiceMock.isEngineInitialized()).thenReturn(true);
when(mSyncServiceMock.isUsingExplicitPassphrase()).thenReturn(false);
assertTrue(
PasswordManagerHelper.isSyncingPasswordsWithNoCustomPassphrase(mSyncServiceMock));
}
@Test
public void testActivelySyncingPasswordsWithCustomPassphrase() {
when(mSyncServiceMock.hasSyncConsent()).thenReturn(true);
when(mSyncServiceMock.getActiveDataTypes())
.thenReturn(CollectionUtil.newHashSet(DataType.PASSWORDS));
when(mSyncServiceMock.isEngineInitialized()).thenReturn(true);
when(mSyncServiceMock.isUsingExplicitPassphrase()).thenReturn(true);
assertFalse(
PasswordManagerHelper.isSyncingPasswordsWithNoCustomPassphrase(mSyncServiceMock));
}
@Test
public void testCanUseUpmCheckup() {
when(mSyncServiceMock.getSelectedTypes())
.thenReturn(CollectionUtil.newHashSet(UserSelectableType.PASSWORDS));
when(mSyncServiceMock.isSyncFeatureEnabled()).thenReturn(true);
when(mSyncServiceMock.isEngineInitialized()).thenReturn(true);
when(mSyncServiceMock.hasSyncConsent()).thenReturn(true);
when(mPasswordManagerUtilBridgeJniMock.shouldUseUpmWiring(mSyncServiceMock, mPrefService))
.thenReturn(true);
assertTrue(mPasswordManagerHelper.canUseUpm());
}
@Test
public void testCanNotUseUpmCheckupWithoutPasswordType() {
when(mSyncServiceMock.isSyncFeatureEnabled()).thenReturn(true);
when(mSyncServiceMock.isEngineInitialized()).thenReturn(true);
when(mSyncServiceMock.hasSyncConsent()).thenReturn(true);
assertFalse(mPasswordManagerHelper.canUseUpm());
}
@Test
public void testCanNotUseUpmCheckupWithoutSyncService() {
when(mSyncServiceMock.isEngineInitialized()).thenReturn(false);
when(mSyncServiceMock.hasSyncConsent()).thenReturn(true);
assertFalse(mPasswordManagerHelper.canUseUpm());
}
@Test
public void testCanNotUseUpmCheckupWithoutSyncConsent() {
when(mSyncServiceMock.isEngineInitialized()).thenReturn(true);
when(mSyncServiceMock.hasSyncConsent()).thenReturn(false);
assertFalse(mPasswordManagerHelper.canUseUpm());
}
@Test
public void testCanNotUseUpmCheckupWithAuthError() {
when(mSyncServiceMock.isEngineInitialized()).thenReturn(true);
when(mSyncServiceMock.hasSyncConsent()).thenReturn(true);
when(mSyncServiceMock.getAuthError()).thenReturn(State.INVALID_GAIA_CREDENTIALS);
assertFalse(mPasswordManagerHelper.canUseUpm());
}
@Test
public void testCanNotUseUpmCheckupWithNoBackend() {
when(mSyncServiceMock.getSelectedTypes())
.thenReturn(CollectionUtil.newHashSet(UserSelectableType.PASSWORDS));
when(mSyncServiceMock.isSyncFeatureEnabled()).thenReturn(true);
when(mSyncServiceMock.isEngineInitialized()).thenReturn(true);
when(mSyncServiceMock.hasSyncConsent()).thenReturn(true);
when(mBackendSupportHelperMock.isBackendPresent()).thenReturn(false);
assertFalse(mPasswordManagerHelper.canUseUpm());
}
@Test
public void testCanUseUpmCheckupWhenBackendUpdateNeeded() {
when(mSyncServiceMock.getSelectedTypes())
.thenReturn(CollectionUtil.newHashSet(UserSelectableType.PASSWORDS));
when(mSyncServiceMock.isSyncFeatureEnabled()).thenReturn(true);
when(mSyncServiceMock.isEngineInitialized()).thenReturn(true);
when(mSyncServiceMock.hasSyncConsent()).thenReturn(true);
when(mPasswordManagerUtilBridgeJniMock.shouldUseUpmWiring(mSyncServiceMock, mPrefService))
.thenReturn(true);
// TODO(crbug.com/40841269): Replace with fakes
when(mBackendSupportHelperMock.isBackendPresent()).thenReturn(true);
when(mPasswordManagerUtilBridgeJniMock.areMinUpmRequirementsMet()).thenReturn(false);
assertTrue(mPasswordManagerHelper.canUseUpm());
}
@Test
public void testShowsUpdateDialogOnShowPasswordSettingsWhenBackendUpdateNeeded()
throws CredentialManagerBackendException {
chooseToSyncPasswords();
when(mBackendSupportHelperMock.isBackendPresent()).thenReturn(true);
when(mPasswordManagerUtilBridgeJniMock.areMinUpmRequirementsMet()).thenReturn(false);
when(mCredentialManagerLauncherFactoryMock.createLauncher())
.thenThrow(
new CredentialManagerBackendException(
"", CredentialManagerError.BACKEND_VERSION_NOT_SUPPORTED));
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_EMAIL_ADDRESS);
assertNotNull(mModalDialogManager.getCurrentDialogForTest());
}
@Test
public void testShowsUpdateDialogOnShowPasswordSettingsWhenGmsCoreUpdateIsRequired() {
when(mBackendSupportHelperMock.isBackendPresent()).thenReturn(true);
when(mPasswordManagerUtilBridgeJniMock.isGmsCoreUpdateRequired(any(), any()))
.thenReturn(true);
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_NO_EMAIL_ADDRESS);
PropertyModel dialogModel = mModalDialogManager.getCurrentDialogForTest();
Context context = RuntimeEnvironment.getApplication().getApplicationContext();
assertNotNull(dialogModel);
assertThat(
dialogModel.get(ModalDialogProperties.MESSAGE_PARAGRAPH_1),
is(context.getString(R.string.password_manager_outdated_gms_dialog_description)));
}
@Test
public void testShowsUpdateDialogOnShowPasswordCheckupForAccountWhenBackendUpdateNeeded()
throws PasswordCheckBackendException {
chooseToSyncPasswords();
when(mBackendSupportHelperMock.isBackendPresent()).thenReturn(true);
when(mPasswordManagerUtilBridgeJniMock.areMinUpmRequirementsMet()).thenReturn(false);
when(mPasswordCheckupClientHelperFactoryMock.createHelper())
.thenThrow(
new PasswordCheckBackendException(
"", CredentialManagerError.BACKEND_VERSION_NOT_SUPPORTED));
mPasswordManagerHelper.showPasswordCheckup(
ContextUtils.getApplicationContext(),
PasswordCheckReferrer.SAFETY_CHECK,
mModalDialogManagerSupplier,
TEST_EMAIL_ADDRESS);
assertNotNull(mModalDialogManager.getCurrentDialogForTest());
}
@Test
public void testShowsUpdateDialogOnShowPasswordCheckupForLocalWhenBackendUpdateNeeded()
throws PasswordCheckBackendException {
chooseToSyncPasswords();
when(mBackendSupportHelperMock.isBackendPresent()).thenReturn(true);
when(mPasswordManagerUtilBridgeJniMock.areMinUpmRequirementsMet()).thenReturn(false);
when(mPasswordCheckupClientHelperFactoryMock.createHelper())
.thenThrow(
new PasswordCheckBackendException(
"", CredentialManagerError.BACKEND_VERSION_NOT_SUPPORTED));
mPasswordManagerHelper.showPasswordCheckup(
ContextUtils.getApplicationContext(),
PasswordCheckReferrer.SAFETY_CHECK,
mModalDialogManagerSupplier,
TEST_NO_EMAIL_ADDRESS);
assertNotNull(mModalDialogManager.getCurrentDialogForTest());
}
@Test
public void testDoesNotShowUpdateDialogOnShowPasswordSettingsWhenNoUpdateNeeded() {
chooseToSyncPasswords();
when(mBackendSupportHelperMock.isBackendPresent()).thenReturn(true);
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_EMAIL_ADDRESS);
assertNull(mModalDialogManager.getCurrentDialogForTest());
}
@Test
public void testDoesNotShowUpdateDialogOnShowPasswordCheckupForAccountWhenNoUpdateNeeded() {
chooseToSyncPasswords();
when(mBackendSupportHelperMock.isBackendPresent()).thenReturn(true);
mPasswordManagerHelper.showPasswordCheckup(
ContextUtils.getApplicationContext(),
PasswordCheckReferrer.SAFETY_CHECK,
mModalDialogManagerSupplier,
TEST_EMAIL_ADDRESS);
assertNull(mModalDialogManager.getCurrentDialogForTest());
}
@Test
public void testDoesNotShowUpdateDialogOnShowPasswordCheckupForLocalWhenNoUpdateNeeded() {
chooseToSyncPasswords();
when(mBackendSupportHelperMock.isBackendPresent()).thenReturn(true);
mPasswordManagerHelper.showPasswordCheckup(
ContextUtils.getApplicationContext(),
PasswordCheckReferrer.SAFETY_CHECK,
mModalDialogManagerSupplier,
TEST_NO_EMAIL_ADDRESS);
assertNull(mModalDialogManager.getCurrentDialogForTest());
}
@Test
public void testSendsIntentOnLaunchGmsUpdate() {
Context mockContext = mock(Context.class);
PasswordManagerHelper.launchGmsUpdate(mockContext);
doAnswer(
invocation -> {
Intent intent = invocation.getArgument(0);
assertEquals(intent.getAction(), Intent.ACTION_VIEW);
assertEquals(intent.getPackage(), "com.android.vending");
assertEquals(intent.getBooleanExtra("overlay", false), true);
assertEquals(
intent.getStringExtra("callerId"),
mockContext.getPackageName());
assertEquals(
intent.getData(),
Uri.parse(
"market://details?id="
+ GoogleApiAvailability
.GOOGLE_PLAY_SERVICES_PACKAGE
+ "&referrer=chrome_upm"));
return null;
})
.when(mockContext)
.startActivity(any(Intent.class));
}
@Test
public void testResetsUnenrollment() {
when(mSyncServiceMock.getSelectedTypes())
.thenReturn(CollectionUtil.newHashSet(UserSelectableType.PASSWORDS));
when(mSyncServiceMock.isSyncFeatureEnabled()).thenReturn(true);
when(mSyncServiceMock.isEngineInitialized()).thenReturn(true);
when(mSyncServiceMock.hasSyncConsent()).thenReturn(true);
when(mPrefService.getBoolean(Pref.UNENROLLED_FROM_GOOGLE_MOBILE_SERVICES_DUE_TO_ERRORS))
.thenReturn(true);
mPasswordManagerHelper.resetUpmUnenrollment();
verify(mPrefService)
.setBoolean(
eq(Pref.UNENROLLED_FROM_GOOGLE_MOBILE_SERVICES_DUE_TO_ERRORS), eq(false));
}
@Test
public void testDoesntResetUnenrollmentIfUnnecessary() {
when(mSyncServiceMock.getSelectedTypes())
.thenReturn(CollectionUtil.newHashSet(UserSelectableType.PASSWORDS));
when(mSyncServiceMock.isSyncFeatureEnabled()).thenReturn(true);
when(mSyncServiceMock.isEngineInitialized()).thenReturn(true);
when(mSyncServiceMock.hasSyncConsent()).thenReturn(true);
when(mPrefService.getBoolean(Pref.UNENROLLED_FROM_GOOGLE_MOBILE_SERVICES_DUE_TO_ERRORS))
.thenReturn(false);
mPasswordManagerHelper.resetUpmUnenrollment();
// If the pref isn't set, don't touch the pref!
verify(mPrefService, never())
.setBoolean(
eq(Pref.UNENROLLED_FROM_GOOGLE_MOBILE_SERVICES_DUE_TO_ERRORS),
anyBoolean());
}
@Test
public void testShowPasswordSettingsSyncingPasswordsLaunchesNewUIForAccount() {
chooseToSyncPasswords();
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_EMAIL_ADDRESS);
verify(mCredentialManagerLauncherMock)
.getAccountCredentialManagerIntent(
eq(ManagePasswordsReferrer.CHROME_SETTINGS),
eq(TEST_EMAIL_ADDRESS),
any(Callback.class),
any(Callback.class));
}
@Test
public void testShowPasswordSettingsSyncingUserNotSyncingPasswordsLaunchesOldUI() {
chooseToSyncButNotSyncPasswords();
Context mockContext = mock(Context.class);
// Set the adequate PasswordManagerUtilBridge response for shouldUseUpmWiring for a syncing
// user who isn't syncing passwords and isn't eligible to use UPM for local.
when(mPasswordManagerUtilBridgeJniMock.shouldUseUpmWiring(mSyncServiceMock, mPrefService))
.thenReturn(false);
mPasswordManagerHelper.showPasswordSettings(
mockContext,
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_EMAIL_ADDRESS);
verify(mockContext).startActivity(any());
verify(mSettingsLauncherMock)
.createSettingsActivityIntent(
eq(mockContext), eq(SettingsFragment.PASSWORDS), any(Bundle.class));
}
@Test
public void testShowPasswordSettingsNotSyncingPasswordsCanNotUseUPMLaunchesOldUI() {
when(mSyncServiceMock.isSyncFeatureEnabled()).thenReturn(false);
Context mockContext = mock(Context.class);
mPasswordManagerHelper.showPasswordSettings(
mockContext,
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_NO_EMAIL_ADDRESS);
verify(mockContext).startActivity(any());
verify(mSettingsLauncherMock)
.createSettingsActivityIntent(
eq(mockContext), eq(SettingsFragment.PASSWORDS), any(Bundle.class));
}
@Test
public void testShowPasswordSettingsNotSyncingPasswordsCanUseUPMLaunchesNewUIForLocal() {
when(mSyncServiceMock.isSyncFeatureEnabled()).thenReturn(false);
when(mPasswordManagerUtilBridgeJniMock.shouldUseUpmWiring(mSyncServiceMock, mPrefService))
.thenReturn(true);
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_NO_EMAIL_ADDRESS);
verify(mCredentialManagerLauncherMock)
.getLocalCredentialManagerIntent(
eq(ManagePasswordsReferrer.CHROME_SETTINGS),
any(Callback.class),
any(Callback.class));
}
@Test
public void testRecordsSuccessMetricsForAccountIntent() {
HistogramWatcher histogram =
HistogramWatcher.newBuilder()
.expectIntRecord(
PasswordMetricsUtil.ACCOUNT_GET_INTENT_LATENCY_HISTOGRAM, 0)
.expectIntRecord(
PasswordMetricsUtil.ACCOUNT_GET_INTENT_SUCCESS_HISTOGRAM, 1)
.expectNoRecords(PasswordMetricsUtil.ACCOUNT_GET_INTENT_ERROR_HISTOGRAM)
.expectIntRecord(
PasswordMetricsUtil
.ACCOUNT_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM,
1)
.build();
chooseToSyncPasswords();
setUpSuccessfulIntentFetchingForAccount();
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testRecordsSuccessMetricsForLocalIntent() {
HistogramWatcher histogram =
HistogramWatcher.newBuilder()
.expectIntRecord(PasswordMetricsUtil.LOCAL_GET_INTENT_LATENCY_HISTOGRAM, 0)
.expectIntRecord(PasswordMetricsUtil.LOCAL_GET_INTENT_SUCCESS_HISTOGRAM, 1)
.expectNoRecords(PasswordMetricsUtil.LOCAL_GET_INTENT_ERROR_HISTOGRAM)
.expectIntRecord(
PasswordMetricsUtil
.LOCAL_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM,
1)
.build();
when(mSyncServiceMock.isSyncFeatureEnabled()).thenReturn(false);
when(mPasswordManagerUtilBridgeJniMock.shouldUseUpmWiring(mSyncServiceMock, mPrefService))
.thenReturn(true);
setUpSuccessfulIntentFetchingForLocal();
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_NO_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testRecordsErrorMetricsForAccountIntent() {
HistogramWatcher histogram =
HistogramWatcher.newBuilder()
.expectIntRecord(
PasswordMetricsUtil.ACCOUNT_GET_INTENT_ERROR_HISTOGRAM,
CredentialManagerError.UNCATEGORIZED)
.expectIntRecord(
PasswordMetricsUtil.ACCOUNT_GET_INTENT_SUCCESS_HISTOGRAM, 0)
.expectNoRecords(PasswordMetricsUtil.ACCOUNT_GET_INTENT_LATENCY_HISTOGRAM)
.expectNoRecords(
PasswordMetricsUtil
.ACCOUNT_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM)
.build();
chooseToSyncPasswords();
returnErrorWhenFetchingIntentForAccount(CredentialManagerError.UNCATEGORIZED);
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testRecordsErrorMetricsForLocalIntent() {
HistogramWatcher histogram =
HistogramWatcher.newBuilder()
.expectIntRecord(
PasswordMetricsUtil.LOCAL_GET_INTENT_ERROR_HISTOGRAM,
CredentialManagerError.UNCATEGORIZED)
.expectIntRecord(PasswordMetricsUtil.LOCAL_GET_INTENT_SUCCESS_HISTOGRAM, 0)
.expectNoRecords(PasswordMetricsUtil.LOCAL_GET_INTENT_LATENCY_HISTOGRAM)
.expectNoRecords(
PasswordMetricsUtil
.LOCAL_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM)
.build();
when(mSyncServiceMock.isSyncFeatureEnabled()).thenReturn(false);
when(mPasswordManagerUtilBridgeJniMock.shouldUseUpmWiring(mSyncServiceMock, mPrefService))
.thenReturn(true);
returnErrorWhenFetchingIntentForLocal(CredentialManagerError.UNCATEGORIZED);
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_NO_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testRecordsMetricsWhenAccountIntentFails() throws CanceledException {
HistogramWatcher histogram =
HistogramWatcher.newBuilder()
.expectIntRecord(
PasswordMetricsUtil.ACCOUNT_GET_INTENT_LATENCY_HISTOGRAM, 0)
.expectIntRecord(
PasswordMetricsUtil.ACCOUNT_GET_INTENT_SUCCESS_HISTOGRAM, 1)
.expectNoRecords(PasswordMetricsUtil.ACCOUNT_GET_INTENT_ERROR_HISTOGRAM)
.expectIntRecord(
PasswordMetricsUtil
.ACCOUNT_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM,
0)
.build();
chooseToSyncPasswords();
setUpSuccessfulIntentFetchingForAccount();
doThrow(CanceledException.class).when(mPendingIntentMock).send();
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testRecordsMetricsWhenLocalIntentFails() throws CanceledException {
HistogramWatcher histogram =
HistogramWatcher.newBuilder()
.expectIntRecord(PasswordMetricsUtil.LOCAL_GET_INTENT_LATENCY_HISTOGRAM, 0)
.expectIntRecord(PasswordMetricsUtil.LOCAL_GET_INTENT_SUCCESS_HISTOGRAM, 1)
.expectNoRecords(PasswordMetricsUtil.LOCAL_GET_INTENT_ERROR_HISTOGRAM)
.expectIntRecord(
PasswordMetricsUtil
.LOCAL_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM,
0)
.build();
when(mSyncServiceMock.isSyncFeatureEnabled()).thenReturn(false);
when(mPasswordManagerUtilBridgeJniMock.shouldUseUpmWiring(mSyncServiceMock, mPrefService))
.thenReturn(true);
setUpSuccessfulIntentFetchingForLocal();
doThrow(CanceledException.class).when(mPendingIntentMock).send();
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_NO_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testLaunchesPasswordCheckupSync() {
chooseToSyncPasswords();
mPasswordManagerHelper.showPasswordCheckup(
ContextUtils.getApplicationContext(),
PasswordCheckReferrer.SAFETY_CHECK,
mModalDialogManagerSupplier,
TEST_EMAIL_ADDRESS);
verify(mPasswordCheckupClientHelperMock)
.getPasswordCheckupIntent(
eq(PasswordCheckReferrer.SAFETY_CHECK),
eq(Optional.of(TEST_EMAIL_ADDRESS)),
any(Callback.class),
any(Callback.class));
}
@Test
public void testRetrievesIntentForLocalCheckup() {
when(mPasswordManagerUtilBridgeJniMock.shouldUseUpmWiring(mSyncServiceMock, mPrefService))
.thenReturn(true);
mPasswordManagerHelper.showPasswordCheckup(
ContextUtils.getApplicationContext(),
PasswordCheckReferrer.SAFETY_CHECK,
mModalDialogManagerSupplier,
TEST_NO_EMAIL_ADDRESS);
verify(mPasswordCheckupClientHelperMock)
.getPasswordCheckupIntent(
eq(PasswordCheckReferrer.SAFETY_CHECK),
eq(Optional.empty()),
any(Callback.class),
any(Callback.class));
}
@Test
public void testPasswordCheckupIntentForAccountCalledIfSuccess() throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_EMAIL_ADDRESS);
mPasswordManagerHelper.showPasswordCheckup(
ContextUtils.getApplicationContext(),
PasswordCheckReferrer.SAFETY_CHECK,
mModalDialogManagerSupplier,
TEST_EMAIL_ADDRESS);
verify(mPendingIntentMock).send();
}
@Test
public void testPasswordCheckupIntentForLocalCalledIfSuccess() throws CanceledException {
when(mPasswordManagerUtilBridgeJniMock.shouldUseUpmWiring(mSyncServiceMock, mPrefService))
.thenReturn(true);
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_NO_EMAIL_ADDRESS);
mPasswordManagerHelper.showPasswordCheckup(
ContextUtils.getApplicationContext(),
PasswordCheckReferrer.SAFETY_CHECK,
mModalDialogManagerSupplier,
TEST_NO_EMAIL_ADDRESS);
verify(mPendingIntentMock).send();
}
@Test
public void testRecordsSuccessMetricsForPasswordCheckupIntentForAccount() {
HistogramWatcher.Builder builder =
histogramWatcherBuilderOfPasswordCheckupSuccessHistogramsForOperation(
PasswordCheckOperation.GET_PASSWORD_CHECKUP_INTENT);
HistogramWatcher histogram =
builder.expectIntRecord(
PasswordMetricsUtil
.PASSWORD_CHECKUP_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM,
1)
.build();
chooseToSyncPasswords();
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_EMAIL_ADDRESS);
mPasswordManagerHelper.showPasswordCheckup(
ContextUtils.getApplicationContext(),
PasswordCheckReferrer.SAFETY_CHECK,
mModalDialogManagerSupplier,
TEST_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testRecordsSuccessMetricsForPasswordCheckupIntentForLocal() {
HistogramWatcher.Builder builder =
histogramWatcherBuilderOfPasswordCheckupSuccessHistogramsForOperation(
PasswordCheckOperation.GET_PASSWORD_CHECKUP_INTENT);
HistogramWatcher histogram =
builder.expectIntRecord(
PasswordMetricsUtil
.PASSWORD_CHECKUP_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM,
1)
.build();
when(mPasswordManagerUtilBridgeJniMock.shouldUseUpmWiring(mSyncServiceMock, mPrefService))
.thenReturn(true);
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_NO_EMAIL_ADDRESS);
mPasswordManagerHelper.showPasswordCheckup(
ContextUtils.getApplicationContext(),
PasswordCheckReferrer.SAFETY_CHECK,
mModalDialogManagerSupplier,
TEST_NO_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testRecordsErrorMetricsForPasswordCheckupIntentForAccount() {
HistogramWatcher.Builder builder =
histogramWatcherBuilderOfPasswordCheckupFailureHistogramsForOperation(
PasswordCheckOperation.GET_PASSWORD_CHECKUP_INTENT,
CredentialManagerError.UNCATEGORIZED,
OptionalInt.empty());
HistogramWatcher histogram =
builder.expectNoRecords(
PasswordMetricsUtil
.PASSWORD_CHECKUP_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM)
.build();
chooseToSyncPasswords();
returnErrorWhenFetchingIntentForPasswordCheckup(
new PasswordCheckBackendException("", CredentialManagerError.UNCATEGORIZED),
TEST_EMAIL_ADDRESS);
mPasswordManagerHelper.showPasswordCheckup(
ContextUtils.getApplicationContext(),
PasswordCheckReferrer.SAFETY_CHECK,
mModalDialogManagerSupplier,
TEST_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testRecordsErrorMetricsForPasswordCheckupIntentForLocal() {
HistogramWatcher.Builder builder =
histogramWatcherBuilderOfPasswordCheckupFailureHistogramsForOperation(
PasswordCheckOperation.GET_PASSWORD_CHECKUP_INTENT,
CredentialManagerError.UNCATEGORIZED,
OptionalInt.empty());
HistogramWatcher histogram =
builder.expectNoRecords(
PasswordMetricsUtil
.PASSWORD_CHECKUP_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM)
.build();
when(mPasswordManagerUtilBridgeJniMock.shouldUseUpmWiring(mSyncServiceMock, mPrefService))
.thenReturn(true);
returnErrorWhenFetchingIntentForPasswordCheckup(
new PasswordCheckBackendException("", CredentialManagerError.UNCATEGORIZED),
TEST_NO_EMAIL_ADDRESS);
mPasswordManagerHelper.showPasswordCheckup(
ContextUtils.getApplicationContext(),
PasswordCheckReferrer.SAFETY_CHECK,
mModalDialogManagerSupplier,
TEST_NO_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testRecordsApiErrorMetricsForPasswordCheckupIntentForAccount() {
HistogramWatcher.Builder builder =
histogramWatcherBuilderOfPasswordCheckupFailureHistogramsForOperation(
PasswordCheckOperation.GET_PASSWORD_CHECKUP_INTENT,
CredentialManagerError.API_ERROR,
OptionalInt.of(CommonStatusCodes.DEVELOPER_ERROR));
HistogramWatcher histogram =
builder.expectNoRecords(
PasswordMetricsUtil
.PASSWORD_CHECKUP_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM)
.build();
chooseToSyncPasswords();
returnErrorWhenFetchingIntentForPasswordCheckup(
new ApiException(new Status(CommonStatusCodes.DEVELOPER_ERROR)),
TEST_EMAIL_ADDRESS);
mPasswordManagerHelper.showPasswordCheckup(
ContextUtils.getApplicationContext(),
PasswordCheckReferrer.SAFETY_CHECK,
mModalDialogManagerSupplier,
TEST_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testRecordsApiErrorMetricsForPasswordCheckupIntentForLocal() {
HistogramWatcher.Builder builder =
histogramWatcherBuilderOfPasswordCheckupFailureHistogramsForOperation(
PasswordCheckOperation.GET_PASSWORD_CHECKUP_INTENT,
CredentialManagerError.API_ERROR,
OptionalInt.of(CommonStatusCodes.DEVELOPER_ERROR));
HistogramWatcher histogram =
builder.expectNoRecords(
PasswordMetricsUtil
.PASSWORD_CHECKUP_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM)
.build();
when(mPasswordManagerUtilBridgeJniMock.shouldUseUpmWiring(mSyncServiceMock, mPrefService))
.thenReturn(true);
returnErrorWhenFetchingIntentForPasswordCheckup(
new ApiException(new Status(CommonStatusCodes.DEVELOPER_ERROR)),
TEST_NO_EMAIL_ADDRESS);
mPasswordManagerHelper.showPasswordCheckup(
ContextUtils.getApplicationContext(),
PasswordCheckReferrer.SAFETY_CHECK,
mModalDialogManagerSupplier,
TEST_NO_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testRecordsSuccessMetricsForRunPasswordCheckup() {
HistogramWatcher histogram =
histogramWatcherBuilderOfPasswordCheckupSuccessHistogramsForOperation(
PasswordCheckOperation.RUN_PASSWORD_CHECKUP)
.build();
chooseToSyncPasswords();
setUpSuccessfulRunPasswordCheckup();
mPasswordManagerHelper.runPasswordCheckupInBackground(
PasswordCheckReferrer.SAFETY_CHECK,
TEST_EMAIL_ADDRESS,
mock(Callback.class),
mock(Callback.class));
histogram.assertExpected();
}
@Test
public void testRecordsErrorMetricsForRunPasswordCheckup() {
HistogramWatcher histogram =
histogramWatcherBuilderOfPasswordCheckupFailureHistogramsForOperation(
PasswordCheckOperation.RUN_PASSWORD_CHECKUP,
CredentialManagerError.UNCATEGORIZED,
OptionalInt.empty())
.build();
chooseToSyncPasswords();
returnErrorWhenRunningPasswordCheckup(
new PasswordCheckBackendException("", CredentialManagerError.UNCATEGORIZED));
mPasswordManagerHelper.runPasswordCheckupInBackground(
PasswordCheckReferrer.SAFETY_CHECK,
TEST_EMAIL_ADDRESS,
mock(Callback.class),
mock(Callback.class));
histogram.assertExpected();
}
@Test
public void testRecordsApiErrorMetricsForRunPasswordCheckup() {
HistogramWatcher histogram =
histogramWatcherBuilderOfPasswordCheckupFailureHistogramsForOperation(
PasswordCheckOperation.RUN_PASSWORD_CHECKUP,
CredentialManagerError.API_ERROR,
OptionalInt.of(CommonStatusCodes.DEVELOPER_ERROR))
.build();
chooseToSyncPasswords();
returnErrorWhenRunningPasswordCheckup(
new ApiException(new Status(CommonStatusCodes.DEVELOPER_ERROR)));
mPasswordManagerHelper.runPasswordCheckupInBackground(
PasswordCheckReferrer.SAFETY_CHECK,
TEST_EMAIL_ADDRESS,
mock(Callback.class),
mock(Callback.class));
histogram.assertExpected();
}
@Test
public void testRecordsSuccessMetricsForGetBreachedCredentialsCount() {
HistogramWatcher histogram =
histogramWatcherBuilderOfPasswordCheckupSuccessHistogramsForOperation(
PasswordCheckOperation.GET_BREACHED_CREDENTIALS_COUNT)
.build();
chooseToSyncPasswords();
setUpSuccessfulGetBreachedCredentialsCount();
mPasswordManagerHelper.getBreachedCredentialsCount(
PasswordCheckReferrer.SAFETY_CHECK,
TEST_EMAIL_ADDRESS,
mock(Callback.class),
mock(Callback.class));
histogram.assertExpected();
}
@Test
public void testRecordsErrorMetricsForGetBreachedCredentialsCount() {
HistogramWatcher histogram =
histogramWatcherBuilderOfPasswordCheckupFailureHistogramsForOperation(
PasswordCheckOperation.GET_BREACHED_CREDENTIALS_COUNT,
CredentialManagerError.UNCATEGORIZED,
OptionalInt.empty())
.build();
chooseToSyncPasswords();
returnErrorWhenGettingBreachedCredentialsCount(
new PasswordCheckBackendException("", CredentialManagerError.UNCATEGORIZED));
mPasswordManagerHelper.getBreachedCredentialsCount(
PasswordCheckReferrer.SAFETY_CHECK,
TEST_EMAIL_ADDRESS,
mock(Callback.class),
mock(Callback.class));
histogram.assertExpected();
}
@Test
public void testRecordsApiErrorMetricsForGetBreachedCredentialsCount() {
HistogramWatcher histogram =
histogramWatcherBuilderOfPasswordCheckupFailureHistogramsForOperation(
PasswordCheckOperation.GET_BREACHED_CREDENTIALS_COUNT,
CredentialManagerError.API_ERROR,
OptionalInt.of(CommonStatusCodes.DEVELOPER_ERROR))
.build();
chooseToSyncPasswords();
returnErrorWhenGettingBreachedCredentialsCount(
new ApiException(new Status(CommonStatusCodes.DEVELOPER_ERROR)));
mPasswordManagerHelper.getBreachedCredentialsCount(
PasswordCheckReferrer.SAFETY_CHECK,
TEST_EMAIL_ADDRESS,
mock(Callback.class),
mock(Callback.class));
histogram.assertExpected();
}
@Test
public void testRecordsMetricsWhenPasswordCheckupIntentFails() throws CanceledException {
HistogramWatcher.Builder builder =
histogramWatcherBuilderOfPasswordCheckupSuccessHistogramsForOperation(
PasswordCheckOperation.GET_PASSWORD_CHECKUP_INTENT);
HistogramWatcher histogram =
builder.expectIntRecord(
PasswordMetricsUtil
.PASSWORD_CHECKUP_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM,
0)
.build();
chooseToSyncPasswords();
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_EMAIL_ADDRESS);
doThrow(CanceledException.class).when(mPendingIntentMock).send();
mPasswordManagerHelper.showPasswordCheckup(
ContextUtils.getApplicationContext(),
PasswordCheckReferrer.SAFETY_CHECK,
mModalDialogManagerSupplier,
TEST_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testShowsLoadingDialogOnPasswordCheckup() throws CanceledException {
chooseToSyncPasswords();
mPasswordManagerHelper.launchPasswordCheckup(
PasswordCheckReferrer.SAFETY_CHECK,
Optional.of(TEST_EMAIL_ADDRESS),
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext());
verify(mLoadingModalDialogCoordinator).show();
}
@Test
public void testDismissesLoadingDialogWhenPasswordCheckupIntentSent() throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_EMAIL_ADDRESS);
mPasswordManagerHelper.launchPasswordCheckup(
PasswordCheckReferrer.SAFETY_CHECK,
Optional.of(TEST_EMAIL_ADDRESS),
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext());
verify(mLoadingModalDialogCoordinator).dismiss();
}
@Test
public void testDismissesLoadingDialogOnPasswordCheckupIntentSendError()
throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_EMAIL_ADDRESS);
doThrow(CanceledException.class).when(mPendingIntentMock).send();
mPasswordManagerHelper.launchPasswordCheckup(
PasswordCheckReferrer.SAFETY_CHECK,
Optional.of(TEST_EMAIL_ADDRESS),
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext());
verify(mLoadingModalDialogCoordinator).dismiss();
}
@Test
public void testDismissesLoadingDialogOnPasswordCheckupIntentGetError()
throws CanceledException {
chooseToSyncPasswords();
returnErrorWhenFetchingIntentForPasswordCheckup(
new PasswordCheckBackendException("", CredentialManagerError.UNCATEGORIZED),
TEST_EMAIL_ADDRESS);
mPasswordManagerHelper.launchPasswordCheckup(
PasswordCheckReferrer.SAFETY_CHECK,
Optional.of(TEST_EMAIL_ADDRESS),
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext());
verify(mLoadingModalDialogCoordinator).dismiss();
}
@Test
public void testDoesNotLaunchPasswordCheckupIntentWhenLoadingDialogCancelled()
throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_EMAIL_ADDRESS);
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.CANCELLED);
mPasswordManagerHelper.launchPasswordCheckup(
PasswordCheckReferrer.SAFETY_CHECK,
Optional.of(TEST_EMAIL_ADDRESS),
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext());
verify(mPendingIntentMock, never()).send();
}
@Test
public void testDoesNotLaunchPasswordCheckupIntentWhenLoadingDialogTimedOut()
throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_EMAIL_ADDRESS);
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.TIMED_OUT);
mPasswordManagerHelper.launchPasswordCheckup(
PasswordCheckReferrer.SAFETY_CHECK,
Optional.of(TEST_EMAIL_ADDRESS),
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext());
verify(mPendingIntentMock, never()).send();
}
@Test
public void testPasswordCheckupLaunchWaitsForDialogDismissability() throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_EMAIL_ADDRESS);
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.SHOWN);
mPasswordManagerHelper.launchPasswordCheckup(
PasswordCheckReferrer.SAFETY_CHECK,
Optional.of(TEST_EMAIL_ADDRESS),
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext());
verify(mPendingIntentMock, never()).send();
mLoadingDialogCoordinatorObserver.onDismissable();
verify(mPendingIntentMock).send();
}
@Test
public void testShowsLoadingDialogOnPasswordSettings() throws CanceledException {
chooseToSyncPasswords();
mPasswordManagerHelper.launchTheCredentialManager(
ManagePasswordsReferrer.CHROME_SETTINGS,
mSyncServiceMock,
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext(),
TEST_EMAIL_ADDRESS);
verify(mLoadingModalDialogCoordinator).show();
}
@Test
public void testDismissesLoadingDialogWhenPasswordSettingsIntentSent()
throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulIntentFetchingForAccount();
mPasswordManagerHelper.launchTheCredentialManager(
ManagePasswordsReferrer.CHROME_SETTINGS,
mSyncServiceMock,
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext(),
TEST_EMAIL_ADDRESS);
verify(mLoadingModalDialogCoordinator).dismiss();
}
@Test
public void testDismissesLoadingDialogOnPasswordSettingsIntentSendError()
throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulIntentFetchingForAccount();
doThrow(CanceledException.class).when(mPendingIntentMock).send();
mPasswordManagerHelper.launchTheCredentialManager(
ManagePasswordsReferrer.CHROME_SETTINGS,
mSyncServiceMock,
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext(),
TEST_EMAIL_ADDRESS);
verify(mLoadingModalDialogCoordinator).dismiss();
}
@Test
public void testDismissesLoadingDialogOnPasswordSettingsIntentGetError()
throws CanceledException {
chooseToSyncPasswords();
returnErrorWhenFetchingIntentForAccount(CredentialManagerError.API_ERROR);
mPasswordManagerHelper.launchTheCredentialManager(
ManagePasswordsReferrer.CHROME_SETTINGS,
mSyncServiceMock,
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext(),
TEST_EMAIL_ADDRESS);
verify(mLoadingModalDialogCoordinator).dismiss();
}
@Test
public void testDoesNotLaunchPasswordSettingsIntentWhenLoadingDialogCancelled()
throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulIntentFetchingForAccount();
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.CANCELLED);
mPasswordManagerHelper.launchTheCredentialManager(
ManagePasswordsReferrer.CHROME_SETTINGS,
mSyncServiceMock,
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext(),
TEST_EMAIL_ADDRESS);
verify(mPendingIntentMock, never()).send();
}
@Test
public void testDoesNotLaunchPasswordSettingsIntentWhenLoadingDialogTimedOut()
throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulIntentFetchingForAccount();
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.TIMED_OUT);
mPasswordManagerHelper.launchTheCredentialManager(
ManagePasswordsReferrer.CHROME_SETTINGS,
mSyncServiceMock,
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext(),
TEST_EMAIL_ADDRESS);
verify(mPendingIntentMock, never()).send();
}
@Test
public void testPasswordSettingsLaunchWaitsForDialogDismissability() throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulIntentFetchingForAccount();
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.SHOWN);
mPasswordManagerHelper.launchTheCredentialManager(
ManagePasswordsReferrer.CHROME_SETTINGS,
mSyncServiceMock,
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext(),
TEST_EMAIL_ADDRESS);
verify(mPendingIntentMock, never()).send();
mLoadingDialogCoordinatorObserver.onDismissable();
verify(mPendingIntentMock).send();
}
@Test
public void testRecordsSettingsLoadingDialogMetricsOnDialogNotShown() throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulIntentFetchingForAccount();
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.PENDING);
mPasswordManagerHelper.launchTheCredentialManager(
ManagePasswordsReferrer.CHROME_SETTINGS,
mSyncServiceMock,
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext(),
TEST_EMAIL_ADDRESS);
verify(mLoadingModalDialogCoordinator).dismiss();
}
@Test
public void testRecordsSettingsLoadingDialogMetricsOnDialogShownDismissable()
throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulIntentFetchingForAccount();
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.SHOWN);
when(mLoadingModalDialogCoordinator.isImmediatelyDismissable()).thenReturn(true);
mPasswordManagerHelper.launchTheCredentialManager(
ManagePasswordsReferrer.CHROME_SETTINGS,
mSyncServiceMock,
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext(),
TEST_EMAIL_ADDRESS);
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
verify(mLoadingModalDialogCoordinator).dismiss();
}
@Test
public void testRecordsSettingsLoadingDialogMetricsOnDialogShownNonDismissable()
throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulIntentFetchingForAccount();
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.SHOWN);
when(mLoadingModalDialogCoordinator.isImmediatelyDismissable()).thenReturn(false);
mPasswordManagerHelper.launchTheCredentialManager(
ManagePasswordsReferrer.CHROME_SETTINGS,
mSyncServiceMock,
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext(),
TEST_EMAIL_ADDRESS);
mLoadingDialogCoordinatorObserver.onDismissable();
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
verify(mLoadingModalDialogCoordinator).dismiss();
}
@Test
public void testRecordsSettingsLoadingDialogMetricsOnDialogCancelled()
throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulIntentFetchingForAccount();
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.CANCELLED);
mPasswordManagerHelper.launchTheCredentialManager(
ManagePasswordsReferrer.CHROME_SETTINGS,
mSyncServiceMock,
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext(),
TEST_EMAIL_ADDRESS);
}
@Test
public void testRecordsSettingsLoadingDialogMetricsOnDialogCancelledDuringLoad()
throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulIntentFetchingForAccount();
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.SHOWN);
mPasswordManagerHelper.launchTheCredentialManager(
ManagePasswordsReferrer.CHROME_SETTINGS,
mSyncServiceMock,
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext(),
TEST_EMAIL_ADDRESS);
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.CANCELLED);
mLoadingDialogCoordinatorObserver.onDismissedWithState(
LoadingModalDialogCoordinator.State.CANCELLED);
}
@Test
public void testRecordsSettingsLoadingDialogMetricsOnDialogTimeout() throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulIntentFetchingForAccount();
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.TIMED_OUT);
mPasswordManagerHelper.launchTheCredentialManager(
ManagePasswordsReferrer.CHROME_SETTINGS,
mSyncServiceMock,
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext(),
TEST_EMAIL_ADDRESS);
}
@Test
public void testRecordsSettingsLoadingDialogMetricsOnDialogTimeoutDuringLoad()
throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulIntentFetchingForAccount();
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.SHOWN);
mPasswordManagerHelper.launchTheCredentialManager(
ManagePasswordsReferrer.CHROME_SETTINGS,
mSyncServiceMock,
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext(),
TEST_EMAIL_ADDRESS);
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.TIMED_OUT);
mLoadingDialogCoordinatorObserver.onDismissedWithState(
LoadingModalDialogCoordinator.State.TIMED_OUT);
}
@Test
public void testRecordsSettingsLoadingDialogMetricsOnIntentFetchError()
throws CanceledException {
chooseToSyncPasswords();
returnErrorWhenFetchingIntentForAccount(CredentialManagerError.API_ERROR);
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.PENDING);
mPasswordManagerHelper.launchTheCredentialManager(
ManagePasswordsReferrer.CHROME_SETTINGS,
mSyncServiceMock,
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext(),
TEST_EMAIL_ADDRESS);
verify(mLoadingModalDialogCoordinator).dismiss();
}
@Test
public void testRecordsSettingsLoadingDialogMetricsOnIntentSendError()
throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulIntentFetchingForAccount();
doThrow(CanceledException.class).when(mPendingIntentMock).send();
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.PENDING);
mPasswordManagerHelper.launchTheCredentialManager(
ManagePasswordsReferrer.CHROME_SETTINGS,
mSyncServiceMock,
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext(),
TEST_EMAIL_ADDRESS);
verify(mLoadingModalDialogCoordinator).dismiss();
}
@Test
public void testRecordsCheckupLoadingDialogMetricsOnDialogNotShown() throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_EMAIL_ADDRESS);
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.PENDING);
mPasswordManagerHelper.launchPasswordCheckup(
PasswordCheckReferrer.SAFETY_CHECK,
Optional.of(TEST_EMAIL_ADDRESS),
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext());
verify(mLoadingModalDialogCoordinator).dismiss();
}
@Test
public void testRecordsCheckupLoadingDialogMetricsOnDialogShown() throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_EMAIL_ADDRESS);
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.SHOWN);
when(mLoadingModalDialogCoordinator.isImmediatelyDismissable()).thenReturn(true);
mPasswordManagerHelper.launchPasswordCheckup(
PasswordCheckReferrer.SAFETY_CHECK,
Optional.of(TEST_EMAIL_ADDRESS),
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext());
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
verify(mLoadingModalDialogCoordinator).dismiss();
}
@Test
public void testRecordsCheckupLoadingDialogMetricsOnDialogShownNonDismissable()
throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_EMAIL_ADDRESS);
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.SHOWN);
when(mLoadingModalDialogCoordinator.isImmediatelyDismissable()).thenReturn(false);
mPasswordManagerHelper.launchPasswordCheckup(
PasswordCheckReferrer.SAFETY_CHECK,
Optional.of(TEST_EMAIL_ADDRESS),
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext());
mLoadingDialogCoordinatorObserver.onDismissable();
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
verify(mLoadingModalDialogCoordinator).dismiss();
}
@Test
public void testRecordsCheckupLoadingDialogMetricsOnDialogCancelled() throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_EMAIL_ADDRESS);
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.CANCELLED);
mPasswordManagerHelper.launchPasswordCheckup(
PasswordCheckReferrer.SAFETY_CHECK,
Optional.of(TEST_EMAIL_ADDRESS),
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext());
}
@Test
public void testRecordsCheckupLoadingDialogMetricsOnDialogCancelledDuringLoad()
throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_EMAIL_ADDRESS);
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.SHOWN);
mPasswordManagerHelper.launchPasswordCheckup(
PasswordCheckReferrer.SAFETY_CHECK,
Optional.of(TEST_EMAIL_ADDRESS),
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext());
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.CANCELLED);
mLoadingDialogCoordinatorObserver.onDismissedWithState(
LoadingModalDialogCoordinator.State.CANCELLED);
}
@Test
public void testRecordsCheckupLoadingDialogMetricsOnDialogTimeout() throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_EMAIL_ADDRESS);
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.TIMED_OUT);
mPasswordManagerHelper.launchPasswordCheckup(
PasswordCheckReferrer.SAFETY_CHECK,
Optional.of(TEST_EMAIL_ADDRESS),
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext());
}
@Test
public void testRecordsCheckupLoadingDialogMetricsOnDialogTimeoutDuringLoad()
throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_EMAIL_ADDRESS);
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.SHOWN);
mPasswordManagerHelper.launchPasswordCheckup(
PasswordCheckReferrer.SAFETY_CHECK,
Optional.of(TEST_EMAIL_ADDRESS),
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext());
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.TIMED_OUT);
mLoadingDialogCoordinatorObserver.onDismissedWithState(
LoadingModalDialogCoordinator.State.TIMED_OUT);
}
@Test
public void testRecordsCheckupLoadingDialogMetricsOnIntentFetchError()
throws CanceledException {
chooseToSyncPasswords();
returnErrorWhenFetchingIntentForPasswordCheckup(
new PasswordCheckBackendException("", CredentialManagerError.UNCATEGORIZED),
TEST_EMAIL_ADDRESS);
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.PENDING);
mPasswordManagerHelper.launchPasswordCheckup(
PasswordCheckReferrer.SAFETY_CHECK,
Optional.of(TEST_EMAIL_ADDRESS),
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext());
verify(mLoadingModalDialogCoordinator).dismiss();
}
@Test
public void testRecordsCheckupLoadingDialogMetricsOnIntentSendError() throws CanceledException {
chooseToSyncPasswords();
setUpSuccessfulCheckupIntentFetching(mPendingIntentMock, TEST_EMAIL_ADDRESS);
doThrow(CanceledException.class).when(mPendingIntentMock).send();
when(mLoadingModalDialogCoordinator.getState())
.thenReturn(LoadingModalDialogCoordinator.State.PENDING);
mPasswordManagerHelper.launchPasswordCheckup(
PasswordCheckReferrer.SAFETY_CHECK,
Optional.of(TEST_EMAIL_ADDRESS),
mLoadingModalDialogCoordinator,
mModalDialogManagerSupplier,
ContextUtils.getApplicationContext());
verify(mLoadingModalDialogCoordinator).dismiss();
}
@Test
public void testRecordsErrorMetricsWhenRunPasswordCheckupFails() {
chooseToSyncPasswords();
Exception expectedException =
new PasswordCheckBackendException("", CredentialManagerError.UNCATEGORIZED);
returnErrorWhenRunningPasswordCheckup(expectedException);
mPasswordManagerHelper.runPasswordCheckupInBackground(
PasswordCheckReferrer.SAFETY_CHECK,
TEST_EMAIL_ADDRESS,
mock(Callback.class),
mock(Callback.class));
}
@Test
public void testRecordsErrorMetricsWhenGetBreachedCredentialsCountFails() {
chooseToSyncPasswords();
Exception expectedException =
new PasswordCheckBackendException("", CredentialManagerError.UNCATEGORIZED);
returnErrorWhenGettingBreachedCredentialsCount(expectedException);
mPasswordManagerHelper.getBreachedCredentialsCount(
PasswordCheckReferrer.SAFETY_CHECK,
TEST_EMAIL_ADDRESS,
mock(Callback.class),
mock(Callback.class));
}
@Test
public void testRecordsApiErrorWhenFetchingAccountCredentialManagerIntent() {
HistogramWatcher histogram =
HistogramWatcher.newBuilder()
.expectIntRecord(
PasswordMetricsUtil.ACCOUNT_GET_INTENT_SUCCESS_HISTOGRAM, 0)
.expectIntRecord(
PasswordMetricsUtil.ACCOUNT_GET_INTENT_ERROR_HISTOGRAM,
CredentialManagerError.API_ERROR)
.expectIntRecord(
PasswordMetricsUtil.ACCOUNT_GET_INTENT_API_ERROR_HISTOGRAM,
CommonStatusCodes.INTERNAL_ERROR)
.expectNoRecords(
PasswordMetricsUtil
.ACCOUNT_GET_INTENT_ERROR_CONNECTION_RESULT_CODE_HISTOGRAM)
.expectNoRecords(
PasswordMetricsUtil
.ACCOUNT_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM)
.build();
chooseToSyncPasswords();
ApiException returnedException =
new ApiException(new Status(CommonStatusCodes.INTERNAL_ERROR));
returnApiExceptionWhenFetchingIntentForAccount(returnedException);
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testRecordsApiErrorWhenFetchingLocalCredentialManagerIntent() {
HistogramWatcher histogram =
HistogramWatcher.newBuilder()
.expectIntRecord(PasswordMetricsUtil.LOCAL_GET_INTENT_SUCCESS_HISTOGRAM, 0)
.expectIntRecord(
PasswordMetricsUtil.LOCAL_GET_INTENT_ERROR_HISTOGRAM,
CredentialManagerError.API_ERROR)
.expectNoRecords(
PasswordMetricsUtil
.LOCAL_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM)
.build();
when(mSyncServiceMock.isSyncFeatureEnabled()).thenReturn(false);
when(mPasswordManagerUtilBridgeJniMock.shouldUseUpmWiring(mSyncServiceMock, mPrefService))
.thenReturn(true);
ApiException returnedException =
new ApiException(new Status(CommonStatusCodes.INTERNAL_ERROR));
returnApiExceptionWhenFetchingIntentForLocal(returnedException);
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_NO_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testRecordsConnectionResultWhenFetchingAccountCredentialManagerIntent() {
HistogramWatcher histogram =
HistogramWatcher.newBuilder()
.expectIntRecord(
PasswordMetricsUtil.ACCOUNT_GET_INTENT_SUCCESS_HISTOGRAM, 0)
.expectIntRecord(
PasswordMetricsUtil.ACCOUNT_GET_INTENT_ERROR_HISTOGRAM,
CredentialManagerError.API_ERROR)
.expectIntRecord(
PasswordMetricsUtil.ACCOUNT_GET_INTENT_API_ERROR_HISTOGRAM,
CommonStatusCodes.API_NOT_CONNECTED)
.expectIntRecord(
PasswordMetricsUtil
.ACCOUNT_GET_INTENT_ERROR_CONNECTION_RESULT_CODE_HISTOGRAM,
ConnectionResult.API_UNAVAILABLE)
.expectNoRecords(
PasswordMetricsUtil
.ACCOUNT_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM)
.build();
chooseToSyncPasswords();
ApiException returnedException =
new ApiException(
new Status(new ConnectionResult(ConnectionResult.API_UNAVAILABLE), ""));
returnApiExceptionWhenFetchingIntentForAccount(returnedException);
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testRecordsConnectionResultWhenFetchingLocalCredentialManagerIntent() {
HistogramWatcher histogram =
HistogramWatcher.newBuilder()
.expectIntRecord(PasswordMetricsUtil.LOCAL_GET_INTENT_SUCCESS_HISTOGRAM, 0)
.expectIntRecord(
PasswordMetricsUtil.LOCAL_GET_INTENT_ERROR_HISTOGRAM,
CredentialManagerError.API_ERROR)
.expectNoRecords(
PasswordMetricsUtil
.LOCAL_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM)
.build();
when(mSyncServiceMock.isSyncFeatureEnabled()).thenReturn(false);
when(mPasswordManagerUtilBridgeJniMock.shouldUseUpmWiring(mSyncServiceMock, mPrefService))
.thenReturn(true);
ApiException returnedException =
new ApiException(
new Status(new ConnectionResult(ConnectionResult.API_UNAVAILABLE), ""));
returnApiExceptionWhenFetchingIntentForLocal(returnedException);
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_NO_EMAIL_ADDRESS);
histogram.assertExpected();
}
@Test
public void testUseAccountSettings() {
when(mSyncServiceMock.isEngineInitialized()).thenReturn(false);
assertTrue(PasswordManagerHelper.canUseAccountSettings());
}
@Test
public void testCannotUseAccountSettingsWithNoBackend() {
when(mSyncServiceMock.isEngineInitialized()).thenReturn(false);
when(mBackendSupportHelperMock.isBackendPresent()).thenReturn(false);
assertFalse(PasswordManagerHelper.canUseAccountSettings());
}
@Test
@EnableFeatures(
ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_LOCAL_PASSWORDS_ANDROID_ACCESS_LOSS_WARNING)
public void testPasswordAccessLossDialogNoGmsCore() {
when(mPasswordManagerUtilBridgeJniMock.getPasswordAccessLossWarningType(mPrefService))
.thenReturn(PasswordAccessLossWarningType.NO_GMS_CORE);
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_NO_EMAIL_ADDRESS);
PropertyModel dialogModel = mModalDialogManager.getCurrentDialogForTest();
Context context = RuntimeEnvironment.getApplication().getApplicationContext();
assertEquals(
context.getString(R.string.access_loss_no_gms_title),
dialogModel.get(ModalDialogProperties.TITLE));
assertEquals(
context.getString(R.string.access_loss_no_gms_desc),
dialogModel.get(ModalDialogProperties.MESSAGE_PARAGRAPH_1));
assertEquals(
context.getString(R.string.access_loss_no_gms_positive_button_text),
dialogModel.get(ModalDialogProperties.POSITIVE_BUTTON_TEXT));
assertEquals(
context.getString(R.string.close),
dialogModel.get(ModalDialogProperties.NEGATIVE_BUTTON_TEXT));
}
@Test
@EnableFeatures(
ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_LOCAL_PASSWORDS_ANDROID_ACCESS_LOSS_WARNING)
public void testPasswordAccessLossDialogNoUpm() {
when(mPasswordManagerUtilBridgeJniMock.getPasswordAccessLossWarningType(mPrefService))
.thenReturn(PasswordAccessLossWarningType.NO_UPM);
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_NO_EMAIL_ADDRESS);
PropertyModel dialogModel = mModalDialogManager.getCurrentDialogForTest();
Context context = RuntimeEnvironment.getApplication().getApplicationContext();
assertEquals(
context.getString(R.string.access_loss_update_gms_title),
dialogModel.get(ModalDialogProperties.TITLE));
assertEquals(
context.getString(R.string.access_loss_update_gms_desc),
dialogModel.get(ModalDialogProperties.MESSAGE_PARAGRAPH_1));
assertEquals(
context.getString(R.string.password_manager_outdated_gms_positive_button),
dialogModel.get(ModalDialogProperties.POSITIVE_BUTTON_TEXT));
assertEquals(
context.getString(R.string.password_manager_outdated_gms_negative_button),
dialogModel.get(ModalDialogProperties.NEGATIVE_BUTTON_TEXT));
}
@Test
@EnableFeatures(
ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_LOCAL_PASSWORDS_ANDROID_ACCESS_LOSS_WARNING)
public void testPasswordAccessLossDialogNewGmsMigrationFailed() {
when(mPasswordManagerUtilBridgeJniMock.getPasswordAccessLossWarningType(mPrefService))
.thenReturn(PasswordAccessLossWarningType.NEW_GMS_CORE_MIGRATION_FAILED);
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_NO_EMAIL_ADDRESS);
PropertyModel dialogModel = mModalDialogManager.getCurrentDialogForTest();
Context context = RuntimeEnvironment.getApplication().getApplicationContext();
assertEquals(
context.getString(R.string.access_loss_fix_problem_title),
dialogModel.get(ModalDialogProperties.TITLE));
assertEquals(
context.getString(R.string.access_loss_fix_problem_desc),
dialogModel.get(ModalDialogProperties.MESSAGE_PARAGRAPH_1));
assertEquals(
context.getString(R.string.access_loss_fix_problem_positive_button_text),
dialogModel.get(ModalDialogProperties.POSITIVE_BUTTON_TEXT));
assertEquals(
context.getString(R.string.password_manager_outdated_gms_negative_button),
dialogModel.get(ModalDialogProperties.NEGATIVE_BUTTON_TEXT));
}
@Test
@EnableFeatures(
ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_LOCAL_PASSWORDS_ANDROID_ACCESS_LOSS_WARNING)
public void testPasswordAccessLossDialogNotDisplayed() {
when(mPasswordManagerUtilBridgeJniMock.getPasswordAccessLossWarningType(mPrefService))
.thenReturn(PasswordAccessLossWarningType.NONE);
chooseToSyncPasswords();
when(mBackendSupportHelperMock.isBackendPresent()).thenReturn(true);
mPasswordManagerHelper.showPasswordSettings(
ContextUtils.getApplicationContext(),
ManagePasswordsReferrer.CHROME_SETTINGS,
mModalDialogManagerSupplier,
/* managePasskeys= */ false,
TEST_NO_EMAIL_ADDRESS);
assertNull(mModalDialogManager.getCurrentDialogForTest());
}
private void chooseToSyncPasswords() {
when(mSyncServiceMock.isSyncFeatureEnabled()).thenReturn(true);
when(mSyncServiceMock.getSelectedTypes())
.thenReturn(CollectionUtil.newHashSet(UserSelectableType.PASSWORDS));
when(mSyncServiceMock.getAccountInfo())
.thenReturn(CoreAccountInfo.createFromEmailAndGaiaId(TEST_EMAIL_ADDRESS, "0"));
// Set the adequate PasswordManagerUtilBridge response for shouldUseUpmWiring for a syncing
// user.
when(mPasswordManagerUtilBridgeJniMock.shouldUseUpmWiring(mSyncServiceMock, mPrefService))
.thenReturn(true);
}
@Test
public void testShowMainSettingsAndStartExport() {
Context mockContext = mock(Context.class);
PasswordManagerHelper.showMainSettingsAndStartExport(mockContext);
ArgumentMatcher<Bundle> bundleStartsExport =
(ArgumentMatcher<Bundle>)
bundle -> {
if (!bundle.containsKey(START_PASSWORDS_EXPORT)) return false;
if (!bundle.getBoolean(START_PASSWORDS_EXPORT)) return false;
return true;
};
verify(mSettingsLauncherMock)
.createSettingsActivityIntent(
eq(mockContext), eq(SettingsFragment.MAIN), argThat(bundleStartsExport));
}
private void chooseToSyncButNotSyncPasswords() {
when(mSyncServiceMock.isSyncFeatureEnabled()).thenReturn(true);
when(mSyncServiceMock.getSelectedTypes()).thenReturn(new HashSet<>());
when(mSyncServiceMock.getAccountInfo())
.thenReturn(CoreAccountInfo.createFromEmailAndGaiaId(TEST_EMAIL_ADDRESS, "0"));
}
private void setUpSuccessfulIntentFetchingForAccount() {
doAnswer(
invocation -> {
Callback<PendingIntent> cb = invocation.getArgument(2);
cb.onResult(mPendingIntentMock);
return true;
})
.when(mCredentialManagerLauncherMock)
.getAccountCredentialManagerIntent(
eq(ManagePasswordsReferrer.CHROME_SETTINGS),
eq(TEST_EMAIL_ADDRESS),
any(Callback.class),
any(Callback.class));
}
private void setUpSuccessfulIntentFetchingForLocal() {
doAnswer(
invocation -> {
Callback<PendingIntent> cb = invocation.getArgument(1);
cb.onResult(mPendingIntentMock);
return true;
})
.when(mCredentialManagerLauncherMock)
.getLocalCredentialManagerIntent(
eq(ManagePasswordsReferrer.CHROME_SETTINGS),
any(Callback.class),
any(Callback.class));
}
private void setUpSuccessfulCheckupIntentFetching(PendingIntent intent, String accountEmail) {
doAnswer(
invocation -> {
Callback<PendingIntent> cb = invocation.getArgument(2);
cb.onResult(intent);
return true;
})
.when(mPasswordCheckupClientHelperMock)
.getPasswordCheckupIntent(
anyInt(),
eq(accountEmail == null ? Optional.empty() : Optional.of(accountEmail)),
any(Callback.class),
any(Callback.class));
}
private void returnErrorWhenFetchingIntentForAccount(@CredentialManagerError int error) {
doAnswer(
invocation -> {
Callback<Exception> cb = invocation.getArgument(3);
cb.onResult(new CredentialManagerBackendException("", error));
return true;
})
.when(mCredentialManagerLauncherMock)
.getAccountCredentialManagerIntent(
eq(ManagePasswordsReferrer.CHROME_SETTINGS),
eq(TEST_EMAIL_ADDRESS),
any(Callback.class),
any(Callback.class));
}
private void returnErrorWhenFetchingIntentForLocal(@CredentialManagerError int error) {
doAnswer(
invocation -> {
Callback<Exception> cb = invocation.getArgument(2);
cb.onResult(new CredentialManagerBackendException("", error));
return true;
})
.when(mCredentialManagerLauncherMock)
.getLocalCredentialManagerIntent(
eq(ManagePasswordsReferrer.CHROME_SETTINGS),
any(Callback.class),
any(Callback.class));
}
private void returnApiExceptionWhenFetchingIntentForAccount(ApiException exception) {
doAnswer(
invocation -> {
Callback<Exception> cb = invocation.getArgument(3);
cb.onResult(exception);
return true;
})
.when(mCredentialManagerLauncherMock)
.getAccountCredentialManagerIntent(
eq(ManagePasswordsReferrer.CHROME_SETTINGS),
eq(TEST_EMAIL_ADDRESS),
any(Callback.class),
any(Callback.class));
}
private void returnApiExceptionWhenFetchingIntentForLocal(ApiException exception) {
doAnswer(
invocation -> {
Callback<Exception> cb = invocation.getArgument(2);
cb.onResult(exception);
return true;
})
.when(mCredentialManagerLauncherMock)
.getLocalCredentialManagerIntent(
eq(ManagePasswordsReferrer.CHROME_SETTINGS),
any(Callback.class),
any(Callback.class));
}
private void returnErrorWhenFetchingIntentForPasswordCheckup(
Exception error, String accountEmail) {
doAnswer(
invocation -> {
Callback<Exception> cb = invocation.getArgument(3);
cb.onResult(error);
return true;
})
.when(mPasswordCheckupClientHelperMock)
.getPasswordCheckupIntent(
anyInt(),
eq(accountEmail == null ? Optional.empty() : Optional.of(accountEmail)),
any(Callback.class),
any(Callback.class));
}
private void setUpSuccessfulRunPasswordCheckup() {
doAnswer(
invocation -> {
Callback<Void> cb = invocation.getArgument(2);
cb.onResult(null);
return true;
})
.when(mPasswordCheckupClientHelperMock)
.runPasswordCheckupInBackground(
anyInt(), eq(TEST_EMAIL_ADDRESS), any(Callback.class), any(Callback.class));
}
private void setUpSuccessfulGetBreachedCredentialsCount() {
doAnswer(
invocation -> {
Callback<Integer> cb = invocation.getArgument(2);
cb.onResult(0);
return true;
})
.when(mPasswordCheckupClientHelperMock)
.getBreachedCredentialsCount(
anyInt(), eq(TEST_EMAIL_ADDRESS), any(Callback.class), any(Callback.class));
}
private void returnErrorWhenRunningPasswordCheckup(Exception error) {
doAnswer(
invocation -> {
Callback<Exception> cb = invocation.getArgument(3);
cb.onResult(error);
return true;
})
.when(mPasswordCheckupClientHelperMock)
.runPasswordCheckupInBackground(
anyInt(), eq(TEST_EMAIL_ADDRESS), any(Callback.class), any(Callback.class));
}
private void returnErrorWhenGettingBreachedCredentialsCount(Exception error) {
doAnswer(
invocation -> {
Callback<Exception> cb = invocation.getArgument(3);
cb.onResult(error);
return true;
})
.when(mPasswordCheckupClientHelperMock)
.getBreachedCredentialsCount(
anyInt(), eq(TEST_EMAIL_ADDRESS), any(Callback.class), any(Callback.class));
}
private HistogramWatcher.Builder
histogramWatcherBuilderOfPasswordCheckupSuccessHistogramsForOperation(
@PasswordCheckOperation int operation) {
final String nameWithSuffix =
PasswordMetricsUtil.PASSWORD_CHECKUP_HISTOGRAM_BASE
+ "."
+ getPasswordCheckupHistogramSuffixForOperation(operation);
return HistogramWatcher.newBuilder()
.expectIntRecord(nameWithSuffix + ".Success", 1)
.expectIntRecord(nameWithSuffix + ".Latency", 0)
.expectNoRecords(nameWithSuffix + ".ErrorLatency")
.expectNoRecords(nameWithSuffix + ".Error")
.expectNoRecords(nameWithSuffix + ".ApiError");
}
private HistogramWatcher.Builder
histogramWatcherBuilderOfPasswordCheckupFailureHistogramsForOperation(
@PasswordCheckOperation int operation,
int errorCode,
OptionalInt apiErrorCode) {
final String nameWithSuffix =
PasswordMetricsUtil.PASSWORD_CHECKUP_HISTOGRAM_BASE
+ "."
+ getPasswordCheckupHistogramSuffixForOperation(operation);
HistogramWatcher.Builder builder =
HistogramWatcher.newBuilder()
.expectIntRecord(nameWithSuffix + ".Success", 0)
.expectNoRecords(nameWithSuffix + ".Latency")
.expectIntRecord(nameWithSuffix + ".ErrorLatency", 0)
.expectIntRecord(nameWithSuffix + ".Error", errorCode);
if (apiErrorCode.isPresent()) {
return builder.expectIntRecord(nameWithSuffix + ".APIError", apiErrorCode.getAsInt());
} else {
return builder.expectNoRecords(nameWithSuffix + ".APIError");
}
}
private String getPasswordCheckupHistogramSuffixForOperation(
@PasswordCheckOperation int operation) {
switch (operation) {
case PasswordCheckOperation.RUN_PASSWORD_CHECKUP:
return "RunPasswordCheckup";
case PasswordCheckOperation.GET_BREACHED_CREDENTIALS_COUNT:
return "GetBreachedCredentialsCount";
case PasswordCheckOperation.GET_PASSWORD_CHECKUP_INTENT:
return "GetIntent";
default:
throw new AssertionError();
}
}
}