chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc

// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/autofill/core/browser/autofill_external_delegate.h"

#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>

#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/feature_list.h"
#include "base/i18n/rtl.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/gmock_move_support.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/uuid.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/address_data_manager.h"
#include "components/autofill/core/browser/autofill_compose_delegate.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_form_test_utils.h"
#include "components/autofill/core/browser/autofill_granular_filling_utils.h"
#include "components/autofill/core/browser/autofill_plus_address_delegate.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/browser_autofill_manager.h"
#include "components/autofill/core/browser/browser_autofill_manager_test_api.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/metrics/autofill_in_devtools_metrics.h"
#include "components/autofill/core/browser/metrics/autofill_metrics.h"
#include "components/autofill/core/browser/metrics/granular_filling_metrics.h"
#include "components/autofill/core/browser/metrics/log_event.h"
#include "components/autofill/core/browser/metrics/suggestions_list_metrics.h"
#include "components/autofill/core/browser/mock_autofill_compose_delegate.h"
#include "components/autofill/core/browser/mock_autofill_plus_address_delegate.h"
#include "components/autofill/core/browser/mock_single_field_form_fill_router.h"
#include "components/autofill/core/browser/payments/mock_iban_access_manager.h"
#include "components/autofill/core/browser/payments/payments_autofill_client.h"
#include "components/autofill/core/browser/payments/test_payments_autofill_client.h"
#include "components/autofill/core/browser/payments_data_manager.h"
#include "components/autofill/core/browser/personal_data_manager_observer.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "components/autofill/core/browser/test_browser_autofill_manager.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
#include "components/autofill/core/browser/ui/suggestion.h"
#include "components/autofill/core/browser/ui/suggestion_test_helpers.h"
#include "components/autofill/core/browser/ui/suggestion_type.h"
#include "components/autofill/core/common/aliases.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_data_test_api.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h"
#include "components/autofill/core/common/password_form_fill_data.h"
#include "components/strings/grit/components_strings.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
#include "url/origin.h"

namespace autofill {

namespace {

CreateTestAddressFormData;
CreateTestCreditCardFormData;
CreateTestPersonalInformationFormData;
CreateTestUnclassifiedFormData;
_;
AllOf;
AnyOf;
ElementsAre;
Field;
InSequence;
Matcher;
Mock;
NiceMock;
Property;
Return;
SizeIs;
StartsWith;

SuggestionPosition;

constexpr auto kDefaultTriggerSource =;

// Creates a field by field filling suggestion.
// `guid` is used to set `Suggestion::payload` as
// `Suggestion::Guid(guid)`. This method also sets the
// `Suggestion::field_by_field_filling_type_used` to `fbf_type_used`.
Suggestion CreateFieldByFieldFillingSuggestion(const std::string& guid,
                                               FieldType fbf_type_used) {}

Matcher<const AutofillTriggerDetails&> EqualsAutofillTriggerDetails(
    AutofillTriggerDetails details) {}

template <typename SuggestionsMatcher>
auto PopupOpenArgsAre(
    SuggestionsMatcher suggestions_matcher,
    AutofillSuggestionTriggerSource trigger_source = kDefaultTriggerSource) {}

// TODO(crbug.com/40285811): Unify existing `MockCreditCardAccessManager`s in a
// separate file.
class MockCreditCardAccessManager : public CreditCardAccessManager {};

class MockPersonalDataManager : public TestPersonalDataManager {};

class MockAddressDataManager : public TestAddressDataManager {};

class MockAutofillDriver : public TestAutofillDriver {};

class MockPaymentsAutofillClient : public payments::TestPaymentsAutofillClient {};

class MockAutofillClient : public TestAutofillClient {};

class MockBrowserAutofillManager : public TestBrowserAutofillManager {};

}  // namespace

class AutofillExternalDelegateUnitTest : public testing::Test {};

// Variant for use in cases when we expect the BrowserAutofillManager would
// normally set the |should_show_cards_from_account_option_| bit.
class AutofillExternalDelegateCardsFromAccountTest
    : public AutofillExternalDelegateUnitTest {};

TEST_F(AutofillExternalDelegateUnitTest, GetMainFillingProduct) {}

// Test that the address editor is not shown if there's no Autofill profile with
// the provided GUID.
TEST_F(AutofillExternalDelegateUnitTest, ShowEditorForNonexistingProfile) {}

// Test that the address editor is shown for the GUID identifying existing
// Autofill profile.
TEST_F(AutofillExternalDelegateUnitTest, ShowEditorForExistingProfile) {}

// Test that the editor changes are not persisted if the user has canceled
// editing.
TEST_F(AutofillExternalDelegateUnitTest, UserCancelsEditing) {}

// Test that the manual fallback is re-triggered after user closes the edit
// address profile dialog.
TEST_F(AutofillExternalDelegateUnitTest, UserCancelsEditing_ManualFallback) {}

// Test that the editor changes are persisted if the user has canceled editing.
TEST_F(AutofillExternalDelegateUnitTest, UserSavesEdits) {}

// Test the situation when database changes take long enough for the user to
// open the address editor for the second time.
TEST_F(AutofillExternalDelegateUnitTest,
       UserOpensEditorTwiceBeforeProfileIsPersisted) {}

// Test the situation when AutofillExternalDelegate is destroyed before the
// AddressDataManager observer is notified that all tasks have been processed.
TEST_F(AutofillExternalDelegateUnitTest,
       DelegateIsDestroyedBeforeUpdateIsFinished) {}

// Test that the delete dialog is not shown if there's no Autofill profile with
// the provided GUID.
TEST_F(AutofillExternalDelegateUnitTest,
       ShowDeleteDialogForNonexistingProfile) {}

// Test that the delete dialog is shown for the GUID identifying existing
// Autofill profile.
TEST_F(AutofillExternalDelegateUnitTest, ShowDeleteDialog) {}

// Test that the Autofill profile is not deleted when user cancels the deletion
// process.
TEST_F(AutofillExternalDelegateUnitTest, UserCancelsDeletion) {}

// Test that the manual fallback is re-triggered after user closes the edit
// address profile dialog.
TEST_F(AutofillExternalDelegateUnitTest, UserCancelsDeletion_ManualFallback) {}

// Test that the correct Autofill profile is deleted when the user accepts the
// deletion process.
TEST_F(AutofillExternalDelegateUnitTest, UserAcceptsDeletion) {}

// Test the situation when AutofillExternalDelegate is destroyed before the
// AddressDataManager observer is notified that all tasks have been processed.
TEST_F(AutofillExternalDelegateUnitTest,
       UserOpensDeleteDialogTwiceBeforeProfileIsDeleted) {}

// Test that our external delegate called the virtual methods at the right time.
TEST_F(AutofillExternalDelegateUnitTest, TestExternalDelegateVirtualCalls) {}

// Test that data list elements for a node will appear in the Autofill popup.
TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateDataList) {}

// Test that datalist values can get updated while a popup is showing.
TEST_F(AutofillExternalDelegateUnitTest, UpdateDataListWhileShowingPopup) {}

// Test that we _don't_ de-dupe autofill values against datalist values. We
// keep both with a separator.
TEST_F(AutofillExternalDelegateUnitTest, DuplicateAutofillDatalistValues) {}

// Test that we de-dupe autocomplete values against datalist values, keeping the
// latter in case of a match.
TEST_F(AutofillExternalDelegateUnitTest, DuplicateAutocompleteDatalistValues) {}

// Test that the Autofill popup is able to display warnings explaining why
// Autofill is disabled for a website.
// Regression test for http://crbug.com/247880
TEST_F(AutofillExternalDelegateUnitTest, AutofillWarnings) {}

// Test that Autofill warnings are removed if there are also autocomplete
// entries in the vector.
TEST_F(AutofillExternalDelegateUnitTest,
       AutofillWarningsNotShown_WithSuggestions) {}

// Test that the Autofill delegate doesn't try and fill a form with a
// negative unique id.
TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateInvalidUniqueId) {}

// Test that the Autofill delegate still allows previewing and filling
// specifically of the negative ID for SuggestionType::kIbanEntry.
TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateFillsIbanEntry) {}

// Test that the Autofill delegate still allows previewing and filling
// specifically of the negative ID for
// SuggestionType::kMerchantPromoCodeEntry.
TEST_F(AutofillExternalDelegateUnitTest,
       ExternalDelegateFillsMerchantPromoCodeEntry) {}

// Test that the Autofill delegate routes the merchant promo code suggestions
// footer redirect logic correctly.
TEST_F(AutofillExternalDelegateUnitTest,
       ExternalDelegateMerchantPromoCodeSuggestionsFooter) {}

// Test that the ClearPreview call is only sent if the form was being previewed
// (i.e. it isn't autofilling a password).
TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateClearPreviewedForm) {}

// Test that the popup is hidden once we are done editing the autofill field.
TEST_F(AutofillExternalDelegateUnitTest,
       ExternalDelegateHidePopupAfterEditing) {}

// Test that the driver is directed to accept the data list after being notified
// that the user accepted the data list suggestion.
TEST_F(AutofillExternalDelegateUnitTest,
       ExternalDelegateAcceptDatalistSuggestion) {}

// Test that a11y autofill availability is set to `kNoSuggestions` when
// the popup is open and if it was manually triggered on an unclassified field.
TEST_F(AutofillExternalDelegateUnitTest,
       AutofillSuggestionAvailability_ManuallFallback) {}

// Test that a11y autofill availability is set to `kAutofillAvailable` when
// the popup is open with regular autofill suggestions.
TEST_F(AutofillExternalDelegateUnitTest,
       AutofillSuggestionAvailability_Autofill) {}

// Test that a11y autofill availability is set to `kAutocompleteAvailable` when
// the popup is open with autocomplete suggestions.
TEST_F(AutofillExternalDelegateUnitTest,
       AutofillSuggestionAvailability_Autocomplete) {}

// Test parameter data for asserting filling method metrics depending on the
// suggestion (`SuggestionType`) accepted.
struct FillingMethodMetricsTestParams {};

class FillingMethodMetricsUnitTest
    : public AutofillExternalDelegateUnitTest,
      public ::testing::WithParamInterface<FillingMethodMetricsTestParams> {};

const FillingMethodMetricsTestParams kFillingMethodMetricsTestCases[] =;

// Tests that for a certain `SuggestionType` accepted, the expected
// `FillingMethod` is recorded.
TEST_P(FillingMethodMetricsUnitTest, RecordFillingMethodForPopupType) {}

INSTANTIATE_TEST_SUITE_P();

// Test parameter data for asserting that group filling suggestions
// forward the expected fields to the manager.
struct GroupFillingTestParams {};

class GroupFillingUnitTest
    : public AutofillExternalDelegateUnitTest,
      public ::testing::WithParamInterface<GroupFillingTestParams> {};

const GroupFillingTestParams kGroupFillingTestCases[] =;

// Tests that the expected server field set is forwarded to the manager
// depending on the chosen suggestion.
TEST_P(GroupFillingUnitTest, GroupFillingTests_FillAndPreview) {}

INSTANTIATE_TEST_SUITE_P();

// Test that an accepted autofill suggestion will fill the form.
TEST_F(AutofillExternalDelegateUnitTest, AcceptSuggestion) {}

TEST_F(AutofillExternalDelegateUnitTest,
       TestAddressSuggestionShown_MetricsEmitted) {}

// Test that an accepted test address autofill suggestion will fill the form.
TEST_F(AutofillExternalDelegateUnitTest, TestAddressSuggestion_FillAndPreview) {}

TEST_F(AutofillExternalDelegateUnitTest,
       AcceptFirstPopupLevelSuggestion_LogSuggestionAcceptedMetric) {}

TEST_F(AutofillExternalDelegateUnitTest,
       ExternalDelegateAccept_FillEverythingSuggestion_FillAndPreview) {}

// Tests that when accepting a suggestion, the `AutofillSuggestionTriggerSource`
// is converted to the correct `AutofillTriggerSource`.
TEST_F(AutofillExternalDelegateUnitTest, AcceptSuggestion_TriggerSource) {}

// Tests that when the suggestion is of type
// `SuggestionType::kAddressFieldByFieldFilling`, we emit the expected metric
// corresponding to which field type was used.
TEST_F(AutofillExternalDelegateUnitTest,
       FieldByFieldFilling_SubPopup_EmitsTypeMetric) {}

TEST_F(AutofillExternalDelegateUnitTest,
       FieldByFieldFilling_RootPopup_DoNotEmitTypeMetric) {}

TEST_F(AutofillExternalDelegateUnitTest,
       FieldByFieldFilling_PreviewCreditCard) {}

TEST_F(AutofillExternalDelegateUnitTest,
       FieldByFieldFilling_FillCreditCardName) {}

TEST_F(AutofillExternalDelegateUnitTest,
       FieldByFieldFilling_FillCreditCardNumber_FetchingFailed) {}

TEST_F(AutofillExternalDelegateUnitTest,
       FieldByFieldFilling_FillCreditCardNumber_Fetched) {}

TEST_F(AutofillExternalDelegateUnitTest,
       VirtualCreditCard_ManualFallback_CreditCardForm_Preview) {}

TEST_F(AutofillExternalDelegateUnitTest,
       VirtualCreditCard_ManualFallback_NonCreditCardForm_NoPreview) {}

TEST_F(AutofillExternalDelegateUnitTest,
       VirtualCreditCard_ManualFallback_CreditCardForm_FullFormFilling) {}

TEST_F(AutofillExternalDelegateUnitTest,
       VirtualCreditCard_ManualFallback_FetchingFails) {}

TEST_F(AutofillExternalDelegateUnitTest,
       VirtualCreditCard_ManualFallback_FetchingSucceeds) {}

// Test parameter data for asserting that the expected set of field types
// is stored in the delegate.
struct GetLastFieldTypesToFillForSectionTestParams {};

class GetLastFieldTypesToFillUnitTest
    : public AutofillExternalDelegateUnitTest,
      public ::testing::WithParamInterface<
          GetLastFieldTypesToFillForSectionTestParams> {};

const GetLastFieldTypesToFillForSectionTestParams
    kGetLastFieldTypesToFillForSectionTesCases[] =;

// Tests that the expected set of last field types to fill is stored.
TEST_P(GetLastFieldTypesToFillUnitTest, LastFieldTypesToFillForSection) {}

INSTANTIATE_TEST_SUITE_P();

// Mock out an existing plus address autofill suggestion, and ensure that
// choosing it results in the field being filled with its value (as opposed to
// the mocked address used in the creation flow).
TEST_F(AutofillExternalDelegateUnitTest,
       ExternalDelegateFillsExistingPlusAddress) {}

// Mock out the new plus address creation flow, and ensure that its completion
// results in the field being filled with the resulting plus address.
TEST_F(AutofillExternalDelegateUnitTest,
       ExternalDelegateOffersPlusAddressCreation) {}

// Tests that selecting an inline plus address suggestion previews the value
// stored in the payload.
TEST_F(AutofillExternalDelegateUnitTest, PlusAddressInlineSuggestionSelected) {}

// Tests that selecting an inline plus address suggestion with an empty address
// value does not preview anything.
TEST_F(AutofillExternalDelegateUnitTest,
       PlusAddressInlineSuggestionSelectedWithNoAddress) {}

TEST_F(AutofillExternalDelegateUnitTest,
       ComposeSuggestion_ComposeProactiveNudge_ForwardsCaretBoundsToClient) {}

// Even though the `SuggestionType` is correct and the bounds are valid. The
// caret bounds are not used because the
// `ComposeDelegate::ShouldAnchorNudgeOnCaret()` is returning false.
TEST_F(
    AutofillExternalDelegateUnitTest,
    ComposeSuggestion_ComposeProactiveNudge_ShouldAnchorNudgeOnCaretReturnsFalse_DoNotForwardsCaretBoundsToClient) {}

TEST_F(
    AutofillExternalDelegateUnitTest,
    ComposeSuggestion_ComposeProactiveNudge_CaretOutsideField_DoNotSendCaretBoundsToClient) {}

TEST_F(
    AutofillExternalDelegateUnitTest,
    NonComposeSuggestion_NonComposeProactiveNudge_DoNotForwardsCaretBoundsToClient) {}

// Tests that accepting a Compose suggestion returns a callback that, when run,
// fills the trigger field.
TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateOpensComposeAndFills) {}

TEST_F(AutofillExternalDelegateUnitTest,
       Compose_AcceptDisable_CallsComposeDelegate) {}

TEST_F(AutofillExternalDelegateUnitTest,
       Compose_AcceptGoToSettings_CallsComposeDelegate) {}

TEST_F(AutofillExternalDelegateUnitTest,
       Compose_AcceptNeverShowOnThisWebsiteAgain_CallsComposeDelegate) {}

#if !BUILDFLAG(IS_IOS)
// Test that the driver is directed to clear or undo the form after being
// notified that the user accepted the suggestion to clear or undo the form.
TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateUndoForm) {}

// Test that the driver is directed to undo the form after being notified that
// the user selected the suggestion to undo the form.
TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateUndoPreviewForm) {}
#endif

// Test that autofill client will scan a credit card after use accepted the
// suggestion to scan a credit card.
TEST_F(AutofillExternalDelegateUnitTest, ScanCreditCardMenuItem) {}

TEST_F(AutofillExternalDelegateUnitTest,
       ScanCreditCardMetrics_SuggestionShown) {}

TEST_F(AutofillExternalDelegateUnitTest,
       ScanCreditCardMetrics_SuggestionAccepted) {}

TEST_F(AutofillExternalDelegateUnitTest,
       ScanCreditCardMetrics_DifferentSuggestionAccepted) {}

TEST_F(AutofillExternalDelegateUnitTest,
       ScanCreditCardMetrics_SuggestionNotShown) {}

TEST_F(AutofillExternalDelegateUnitTest, AutocompleteShown_MetricsEmitted) {}

MATCHER_P(CreditCardMatches, card, "") {}

// Test that autofill manager will fill the credit card form after user scans a
// credit card.
TEST_F(AutofillExternalDelegateUnitTest, FillCreditCardForm) {}

TEST_F(AutofillExternalDelegateUnitTest, IgnoreAutocompleteOffForAutofill) {}

TEST_F(AutofillExternalDelegateUnitTest,
       ExternalDelegateFillFieldWithValue_Autocomplete) {}

TEST_F(AutofillExternalDelegateUnitTest,
       ExternalDelegateFillFieldWithValue_MerchantPromoCode) {}

TEST_F(AutofillExternalDelegateUnitTest,
       ExternalDelegateFillFieldWithValue_Iban) {}

TEST_F(AutofillExternalDelegateUnitTest,
       ExternalDelegateFillFieldWithValue_FieldByFieldFilling) {}

// Test that browser autofill manager will handle the unmasking request for the
// virtual card after users accept the suggestion to use a virtual card.
TEST_F(AutofillExternalDelegateUnitTest, AcceptVirtualCardOptionItem) {}

TEST_F(AutofillExternalDelegateUnitTest, SelectVirtualCardOptionItem) {}

class AutofillExternalDelegate_RemoveSuggestionTest
    : public AutofillExternalDelegateUnitTest,
      public ::testing::WithParamInterface<SuggestionType> {};

const SuggestionType kRemoveSuggestionTestCases[] =;

INSTANTIATE_TEST_SUITE_P();

TEST_P(AutofillExternalDelegate_RemoveSuggestionTest, RemoveSuggestion) {}

TEST_F(AutofillExternalDelegateCardsFromAccountTest,
       ShowCardsFromAccountMetrics) {}

TEST_F(AutofillExternalDelegateUnitTest,
       RecordSuggestionTypeOnSuggestionAccepted) {}

// Tests that setting `is_update` to true in
// `AttemptToDisplayAutofillSuggestions` leads to a call to
// `AutofillClient::UpdateAutofillSuggestions`.
TEST_F(AutofillExternalDelegateUnitTest, UpdateSuggestions) {}

// TODO(crbug.com/41483208): Add test case where 'Show cards from your Google
// account' button is clicked. Encountered issues with test sync setup when
// attempting to make it.

#if BUILDFLAG(IS_IOS)
// Tests that outdated returned suggestions are discarded.
TEST_F(AutofillExternalDelegateCardsFromAccountTest,
       ShouldDiscardOutdatedSuggestions) {
  FieldGlobalId old_field_id = test::MakeFieldGlobalId();
  FieldGlobalId new_field_id = test::MakeFieldGlobalId();
  client().set_last_queried_field(new_field_id);
  IssueOnQuery();
  EXPECT_CALL(client(), ShowAutofillSuggestions).Times(0);
  OnSuggestionsReturned(old_field_id, std::vector<Suggestion>());
}
#endif

// Tests logging with the new ranking algorithm experiment for Autofill
// suggestions enabled.
class AutofillExternalDelegateUnitTestWithNewSuggestionRankingAlgorithm
    : public AutofillExternalDelegateUnitTest {};

// Test that the SuggestionRankingDifference metric is logged after a credit
// card suggestion is accepted.
TEST_F(AutofillExternalDelegateUnitTestWithNewSuggestionRankingAlgorithm,
       SuggestionAccepted_LogSuggestionRankingDifference_CreditCard) {}

// Test that the SuggestionRankingDifference metric is not logged after a credit
// card suggestion is accepted if the rankings are the same in both algorithms.
TEST_F(
    AutofillExternalDelegateUnitTestWithNewSuggestionRankingAlgorithm,
    SuggestionAccepted_LogSuggestionRankingDifference_NotLoggedWhenRankingsAreTheSame) {}
}  // namespace autofill