// Copyright 2022 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h" #include <memory> #include <string> #include "base/test/metrics/histogram_tester.h" #include "chrome/browser/ui/views/chrome_constrained_window_views_client.h" #include "chrome/browser/ui/views/webid/account_selection_bubble_view.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/views/chrome_views_test_base.h" #include "components/constrained_window/constrained_window_views.h" #include "content/public/browser/identity_request_dialog_controller.h" #include "content/public/test/test_renderer_host.h" #include "content/public/test/web_contents_tester.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/views/test/mock_input_event_activation_protector.h" #include "url/gurl.h" LoginState; SignInMode; TokenError; DismissReason; namespace { constexpr char kTopFrameEtldPlusOne[] = …; constexpr char kIdpEtldPlusOne[] = …; constexpr char kConfigUrl[] = …; constexpr char kLoginUrl[] = …; constexpr char kAccountId1[] = …; constexpr char kAccountId2[] = …; // Mock AccountSelectionViewBase which tracks state. class TestAccountSelectionView : public AccountSelectionViewBase { … }; // Mock version of FedCmModalDialogView for injection during tests. class MockFedCmModalDialogView : public FedCmModalDialogView { … }; // Test FedCmAccountSelectionView which uses TestAccountSelectionView. class TestFedCmAccountSelectionView : public FedCmAccountSelectionView { … }; // Stub AccountSelectionView::Delegate. class StubAccountSelectionViewDelegate : public AccountSelectionView::Delegate { … }; } // namespace class FedCmAccountSelectionViewDesktopTest : public ChromeViewsTestBase { … }; TEST_F(FedCmAccountSelectionViewDesktopTest, SingleAccountFlow) { … } TEST_F(FedCmAccountSelectionViewDesktopTest, MultipleAccountFlowReturning) { … } TEST_F(FedCmAccountSelectionViewDesktopTest, MultipleAccountFlowBack) { … } // Test transitioning from IdP sign-in status mismatch failure dialog to regular // sign-in dialog. TEST_F(FedCmAccountSelectionViewDesktopTest, IdpSigninStatusMismatchDialogToSigninFlow) { … } // Test transitioning from IdP sign-in status mismatch failure dialog to regular // sign-in dialog while the dialog is hidden. This emulates a user signing // into the IdP in a different tab. TEST_F(FedCmAccountSelectionViewDesktopTest, IdpSigninStatusMismatchDialogToSigninFlowHidden) { … } TEST_F(FedCmAccountSelectionViewDesktopTest, AutoReauthnSingleAccountFlow) { … } namespace { // AccountSelectionViewDelegate which deletes the FedCmAccountSelectionView in // OnAccountSelected(). class ViewDeletingAccountSelectionViewDelegate : public StubAccountSelectionViewDelegate { … }; } // namespace TEST_F(FedCmAccountSelectionViewDesktopTest, AccountSelectedDeletesView) { … } TEST_F(FedCmAccountSelectionViewDesktopTest, ClickProtection) { … } // Tests that when the auth re-authn dialog is closed, the relevant metric is // recorded. TEST_F(FedCmAccountSelectionViewDesktopTest, CloseAutoReauthnSheetMetric) { … } // Tests that when the mismatch dialog is closed through the close icon, the // relevant metric is recorded. TEST_F(FedCmAccountSelectionViewDesktopTest, MismatchDialogDismissedByCloseIconMetric) { … } // Tests that when the mismatch dialog is closed through means other than the // close icon, the relevant metric is recorded. TEST_F(FedCmAccountSelectionViewDesktopTest, MismatchDialogDismissedForOtherReasonsMetric) { … } // Tests that when FedCmAccountSelectionView is destroyed while the mismatch // dialog is open, the relevant metric is recorded. TEST_F(FedCmAccountSelectionViewDesktopTest, MismatchDialogDestroyedMetric) { … } // Tests that when the continue button on the mismatch dialog is clicked, the // relevant metric is recorded. TEST_F(FedCmAccountSelectionViewDesktopTest, MismatchDialogContinueClickedMetric) { … } // Tests that when the continue button on the mismatch dialog is clicked and // then FedCmAccountSelectionView is destroyed, we record only the metric for // the continue button being clicked. TEST_F(FedCmAccountSelectionViewDesktopTest, MismatchDialogContinueClickedThenDestroyedMetric) { … } // Test transitioning from IdP sign-in status mismatch dialog to regular sign-in // dialog. This emulates a user signing into the IdP in a pop-up window and the // pop-up window closes PRIOR to the mismatch dialog being updated to a regular // sign-in dialog. TEST_F(FedCmAccountSelectionViewDesktopTest, IdpSigninStatusPopupClosedBeforeAccountsPopulated) { … } // Test transitioning from IdP sign-in status mismatch dialog to regular sign-in // dialog. This emulates a user signing into the IdP in a pop-up window and the // pop-up window closes AFTER the mismatch dialog has been updated to a regular // sign-in dialog. TEST_F(FedCmAccountSelectionViewDesktopTest, IdpSigninStatusPopupClosedAfterAccountsPopulated) { … } // Test that when user opens a pop-up window to complete the IDP sign-in flow, // we record the appropriate metric when accounts are received but // IdentityProvider.close() is not called. TEST_F(FedCmAccountSelectionViewDesktopTest, IdpSigninStatusAccountsReceivedAndNoPopupClosedByIdpMetric) { … } // Test that when user opens a pop-up window to complete the IDP sign-in flow, // we record the appropriate metric when accounts are not received but // IdentityProvider.close() is called. TEST_F(FedCmAccountSelectionViewDesktopTest, IdpSigninStatusAccountsNotReceivedAndPopupClosedByIdpMetric) { … } // Test that when user opens a pop-up window to complete the IDP sign-in flow, // we record the appropriate metric when accounts are not received and // IdentityProvider.close() is not called. TEST_F(FedCmAccountSelectionViewDesktopTest, IdpSigninStatusAccountsNotReceivedAndNoPopupClosedByIdpMetric) { … } // Test closing the IdP sign-in pop-up window through IdentityProvider.close() // should not close the widget. TEST_F(FedCmAccountSelectionViewDesktopTest, IdpSigninStatusPopupClosedViaIdentityProviderClose) { … } // Test closing the IdP sign-in pop-up window through means other than // IdentityProvider.close() should also close the widget. TEST_F(FedCmAccountSelectionViewDesktopTest, IdpSigninStatusPopupClosedViaPopupDestroyed) { … } // Test that the mismatch dialog can be shown again after the pop-up window is // closed. TEST_F(FedCmAccountSelectionViewDesktopTest, IdpSigninStatusMismatchDialogReshown) { … } // Tests that RP context is properly set for the mismatch UI. TEST_F(FedCmAccountSelectionViewDesktopTest, MismatchDialogWithRpContext) { … } // Tests the following // 1. pop-up window is closed // 2. visibility changes to hidden e.g. user navigates to different tab // 3. Show() is invoked // 4. widget should remain hidden // 5. visibility changes to visible e.g. user navigates back to same tab // 6. widget should now be visible TEST_F(FedCmAccountSelectionViewDesktopTest, BubbleWidgetAfterPopupRemainsHiddenAfterAccountsFetched) { … } // Tests the following // 1. pop-up window is closed // 2. visibility changes to hidden e.g. user navigates to different tab // 3. visibility changes to visible e.g. user navigates back to same tab // 4. widget should remain hidden // 5. Show() is invoked // 6. widget should now be visible TEST_F(FedCmAccountSelectionViewDesktopTest, BubbleWidgetAfterPopupRemainsHiddenBeforeAccountsFetched) { … } // Test transitioning from IdP sign-in status mismatch failure dialog to regular // sign-in dialog where two accounts are logged in at once. TEST_F(FedCmAccountSelectionViewDesktopTest, IdpSigninStatusMismatchMultiAccount) { … } // Test going from mismatch dialog to multiple accounts. TEST_F(FedCmAccountSelectionViewDesktopTest, IdpMismatchToMultipleLoggedInAccounts) { … } // Test the use another account flow, resulting in the new account being shown // after logging in. TEST_F(FedCmAccountSelectionViewDesktopTest, UseAnotherAccount) { … } // Test the use another account flow when signing into the same account that the // user started with. TEST_F(FedCmAccountSelectionViewDesktopTest, UseAnotherAccountForSameAccount) { … } // Test the use another account flow, resulting in account chooser UI if it's a // returning account. TEST_F(FedCmAccountSelectionViewDesktopTest, UseAnotherAccountForReturningAccount) { … } // Test the use another account flow in a modal, resulting in the new account // being shown after logging in. TEST_F(FedCmAccountSelectionViewDesktopTest, UseAnotherAccountModal) { … } // Test the use another account flow in a modal when signing into the same // account that the user started with. TEST_F(FedCmAccountSelectionViewDesktopTest, UseAnotherAccountModalForSameAccount) { … } // Test the use another account flow in a modal, resulting in no account chooser // UI if it's a returning account. TEST_F(FedCmAccountSelectionViewDesktopTest, UseAnotherAccountModalForReturningAccount) { … } // Test the logged-out LoginStatus flow in a modal, resulting in account // chooser UI if it's a returning account. TEST_F(FedCmAccountSelectionViewDesktopTest, LoginStatusLoggedOutModalForReturningAccount) { … } // Test the logged-out LoginStatus flow in a modal, resulting in showing account // chooser UI if it's a non-returning account. TEST_F(FedCmAccountSelectionViewDesktopTest, LoginStatusLoggedOutModalForNonReturningAccount) { … } // Test the browser trusted login state controls whether to skip the account // chooser UI when in conflict with login state. TEST_F(FedCmAccountSelectionViewDesktopTest, BrowserTrustedLoginStateTakesPrecedenceOverLoginState) { … } // Test user triggering the use another account flow twice in a modal, without // closing the pop-up from the first use another account flow. TEST_F(FedCmAccountSelectionViewDesktopTest, UseAnotherAccountTwiceModal) { … } // Test user triggering the use another account flow twice in a modal, with // closing the pop-up from the first use another account flow. TEST_F(FedCmAccountSelectionViewDesktopTest, UseAnotherAccountCloseThenReopenModal) { … } // Test user triggering the use another account flow then clicking on the cancel // button in the modal without completing the use other account flow. TEST_F(FedCmAccountSelectionViewDesktopTest, UseAnotherAccountThenCancel) { … } // Tests that the error dialog can be shown. TEST_F(FedCmAccountSelectionViewDesktopTest, ErrorDialogShown) { … } // Tests that RP context is properly set for the error dialog. TEST_F(FedCmAccountSelectionViewDesktopTest, ErrorDialogWithRpContext) { … } // Tests the flow for when the "got it" button on the error dialog is clicked. TEST_F(FedCmAccountSelectionViewDesktopTest, ErrorDialogGotItClicked) { … } // Tests the flow for when the "more details" button on the error dialog is // clicked. TEST_F(FedCmAccountSelectionViewDesktopTest, ErrorDialogMoreDetailsClicked) { … } TEST_F(FedCmAccountSelectionViewDesktopTest, MultiIdpWithOneIdpMismatch) { … } TEST_F(FedCmAccountSelectionViewDesktopTest, MultiIdpWithSingleReturningAccount) { … } // Tests that closing the dialog when the single returning account UI is shown // does not cause a crash. TEST_F(FedCmAccountSelectionViewDesktopTest, MultiIdpWithSingleReturningAccountClose) { … } // Tests that if a pop-up window is opened in button flow mode, closing the // pop-up window triggers the dismiss callback. TEST_F(FedCmAccountSelectionViewDesktopTest, ButtonFlowPopupCloseTriggersDismissCallback) { … } TEST_F(FedCmAccountSelectionViewDesktopTest, MultiIdpMismatchAndShow) { … } // Tests that if a single account chooser is opened in button flow mode, // selecting an account shows the request permission sheet. Then, confirming the // account on the request permission sheet shows the verifying sheet. TEST_F(FedCmAccountSelectionViewDesktopTest, SingleAccountFlowModal) { … } // Tests that if a multiple account chooser is opened in button flow mode, // selecting an account shows the request permission sheet. Then, confirming the // account on the request permission sheet shows the verifying sheet. TEST_F(FedCmAccountSelectionViewDesktopTest, MultipleAccountFlowModal) { … } // Tests that if a single account chooser is opened in button flow mode, // selecting a returning account shows the verifying sheet. TEST_F(FedCmAccountSelectionViewDesktopTest, SingleAccountFlowReturningModal) { … } // Tests that if a multiple account chooser is opened in button flow mode, // selecting a returning account shows the verifying sheet. TEST_F(FedCmAccountSelectionViewDesktopTest, MultipleAccountFlowReturningModal) { … } // Tests that if a single account chooser is opened in button flow mode, // clicking the back button in the request permission dialog returns the user to // the single account chooser. TEST_F(FedCmAccountSelectionViewDesktopTest, SingleAccountFlowBackModal) { … } // Tests that if a multiple account chooser is opened in button flow mode, // clicking the back button in the request permission dialog returns the user to // the multiple account chooser. TEST_F(FedCmAccountSelectionViewDesktopTest, MultipleAccountFlowBackModal) { … } // Tests that auto re-authn works in button mode. TEST_F(FedCmAccountSelectionViewDesktopTest, AutoReauthnSingleAccountFlowModal) { … } // Tests that the user can dismiss the loading modal. TEST_F(FedCmAccountSelectionViewDesktopTest, DismissLoadingModal) { … } // Tests that the loading modal is not hidden when a pop-up window is displayed. TEST_F(FedCmAccountSelectionViewDesktopTest, ButtonFlowLoadingModalNotHiddenDuringLoginToIdP) { … } // Tests that opening an IDP sign-in pop-up during the loading modal, then // closing the pop-up, does not crash. (This simulates the user triggering a // button flow, then an IDP sign-in pop-up shows up because the user is logged // out) TEST_F(FedCmAccountSelectionViewDesktopTest, CloseIdpSigninPopupDuringLoadingState) { … } // Tests that opening a popup after a verifying sheet, then closing the popup, // notifies the observer. TEST_F(FedCmAccountSelectionViewDesktopTest, UserClosingPopupAfterVerifyingSheetShouldNotify) { … } // Tests that opening a popup after a verifying sheet, then closing the popup // programmatically, does not notify the observer. TEST_F(FedCmAccountSelectionViewDesktopTest, CodeClosingPopupAfterVerifyingSheetShouldNotNotify) { … } // Tests that if the dialog skips requesting permission, the verifying sheet is // shown. TEST_F(FedCmAccountSelectionViewDesktopTest, SkipRequestPermissionShowsVerifying) { … } // Tests that if IDP supports add account, the correct sheet type is shown // depending on the number of accounts and the rp mode. TEST_F(FedCmAccountSelectionViewDesktopTest, SupportAddAccount) { … } // Tests that when adding accounts is supported, the back button is shown even // if there is a single account after logging in. TEST_F(FedCmAccountSelectionViewDesktopTest, IdpSigninStatusMismatchToAccountChooserWithSupportAddAccount) { … } // Tests that the correct account chooser result metrics are recorded. TEST_F(FedCmAccountSelectionViewDesktopTest, AccountChooserResultMetric) { … } // Tests that for button flows, going from an accounts dialog to an error dialog // resets the account selection view. This is needed to switch from modal to // bubble, since the error UI does not have a modal equivalent. TEST_F(FedCmAccountSelectionViewDesktopTest, AccountsToErrorButtonFlowResetsView) { … } // Tests that for button flows, going from a loading dialog to an accounts // dialog does not reset the account selection view. This is important because // the accounts dialog reuses the header from the loading dialog. TEST_F(FedCmAccountSelectionViewDesktopTest, LoadingToAccountsButtonFlowReusesView) { … } // Tests that resizing web contents would update the dialog visibility depending // on whether the dialog can fit within the web contents. TEST_F(FedCmAccountSelectionViewDesktopTest, ResizeWebContentsChangesDialogVisibility) { … } // Tests that resizing web contents in different web contents visibility // scenarios would update the dialog visibility correctly depending on whether // the dialog can fit within the web contents or whether the web contents where // the dialog is contained is visible. TEST_F(FedCmAccountSelectionViewDesktopTest, ResizeWebContentsWithWindowVisibilityChanges) { … } // Tests that changing visibility from hidden to visible, also updates the // dialog position. This is needed in case the web contents was resized while // hidden. TEST_F(FedCmAccountSelectionViewDesktopTest, VisibilityChangesUpdatesDialogPosition) { … } // Tests that the Lens overlay showing hides the dialog until the overlay is // closed. TEST_F(FedCmAccountSelectionViewDesktopTest, LensOverlayHidesDialog) { … } // Tests that the dialog does not open if the Lens overlay is already showing. TEST_F(FedCmAccountSelectionViewDesktopTest, LensOverlaySuppressesDialog) { … } // Test that the fields API (request_permission=false) correctly hides the // disclosure UI after logging in through the popup when logged out. TEST_F(FedCmAccountSelectionViewDesktopTest, RequestPermissionFalseAndNewIdpDataDisclosureText) { … }