[Autofill] Remove the check(!field->is_focusable) for hidden credit cards form after user entered


Design Doc: https://docs.google.com/document/d/1Sm3Yh3xxIcvo3qF2HQpQzJYR3v7K15B516vidtLNYvY/edit?usp=sharing

Change-Id: If9d866d84cda3bf9b31c4db4792cfe6033e459cf
Bug: 926540
Reviewed-on: https://chromium-review.googlesource.com/c/1443629
Reviewed-by: Jared Saul <jsaul@google.com>
Reviewed-by: Elly Fong-Jones <ellyjones@chromium.org>
Reviewed-by: Fabio Tirelo <ftirelo@chromium.org>
Commit-Queue: Hao Zhang <hozhng@google.com>
Cr-Original-Commit-Position: refs/heads/master@{#628429}(cherry picked from commit d301711d4580bbf9d98542b6b9a745cfd54b454d)
Reviewed-on: https://chromium-review.googlesource.com/c/1452474
Cr-Commit-Position: refs/branch-heads/3683@{#177}
Cr-Branched-From: e51029943e0a38dd794b73caaf6373d5496ae783-refs/heads/master@{#625896}
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 35e6218..171c9ed 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2853,6 +2853,13 @@
      kOsAll,
      FEATURE_VALUE_TYPE(
          autofill::features::kAutofillUpstreamEditableExpirationDate)},
+    {"enable-autofill-import-non-focusable-credit-card-forms",
+     flag_descriptions::kEnableAutofillImportNonFocusableCreditCardFormsName,
+     flag_descriptions::
+         kEnableAutofillImportNonFocusableCreditCardFormsDescription,
+     kOsAll,
+     FEATURE_VALUE_TYPE(
+         autofill::features::kAutofillImportNonFocusableCreditCardForms)},
     {"enable-autofill-local-card-migration-show-feedback",
      flag_descriptions::kEnableAutofillLocalCardMigrationShowFeedbackName,
      flag_descriptions::
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 08a2592..35e8b98 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -865,6 +865,11 @@
     "expiry_milestone": 76
   },
   {
+    "name": "enable-autofill-import-non-focusable-credit-card-forms",
+    "owners": [ "hozhng@google.com", "jiahuiguo@google.com" ],
+    "expiry_milestone": 76
+  },
+  {
     "name": "enable-autofill-local-card-migration-show-feedback",
     "owners": [ "jiahuiguo@google.com", "siyua@google.com" ],
     "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index dde5f21..74636e4 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -412,6 +412,13 @@
     "offering card upload to Google Payments, the offer-to-save dialog "
     "displays an expiration date selector.";
 
+const char kEnableAutofillImportNonFocusableCreditCardFormsName[] =
+    "Allow credit card import from forms that disappear after entry";
+const char kEnableAutofillImportNonFocusableCreditCardFormsDescription[] =
+    "If enabled, offers credit card save for forms that are hidden from the "
+    "page after information has been entered into them, including "
+    "accordion-style checkout flows.";
+
 const char kEnableAutofillLocalCardMigrationShowFeedbackName[] =
     "Show the upload results dialog after local card migration";
 const char kEnableAutofillLocalCardMigrationShowFeedbackDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index b41a9dd..d197aee 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -285,6 +285,9 @@
 extern const char
     kEnableAutofillCreditCardUploadEditableExpirationDateDescription[];
 
+extern const char kEnableAutofillImportNonFocusableCreditCardFormsName[];
+extern const char kEnableAutofillImportNonFocusableCreditCardFormsDescription[];
+
 extern const char kEnableAutofillLocalCardMigrationShowFeedbackName[];
 extern const char kEnableAutofillLocalCardMigrationShowFeedbackDescription[];
 
diff --git a/components/autofill/core/browser/form_data_importer.cc b/components/autofill/core/browser/form_data_importer.cc
index df485ac..03b9216 100644
--- a/components/autofill/core/browser/form_data_importer.cc
+++ b/components/autofill/core/browser/form_data_importer.cc
@@ -487,10 +487,17 @@
     base::TrimWhitespace(field->value, base::TRIM_ALL, &value);
 
     // If we don't know the type of the field, or the user hasn't entered any
-    // information into the field, or the field is non-focusable (hidden), then
-    // skip it.
-    if (!field->IsFieldFillable() || !field->is_focusable || value.empty())
+    // information into the field, then skip it.
+    if (!field->IsFieldFillable() || value.empty())
       continue;
+    // If the field is non-focusable (hidden) after the user entered information
+    // into it, then skip it, unless the experiment to import non-focusable
+    // forms is enabled.
+    if (!field->is_focusable &&
+        !base::FeatureList::IsEnabled(
+            features::kAutofillImportNonFocusableCreditCardForms)) {
+      continue;
+    }
 
     AutofillType field_type = field->Type();
     // Field was not identified as a credit card field.
diff --git a/components/autofill/core/browser/form_data_importer.h b/components/autofill/core/browser/form_data_importer.h
index 7fe9efe..0a11aeb 100644
--- a/components/autofill/core/browser/form_data_importer.h
+++ b/components/autofill/core/browser/form_data_importer.h
@@ -152,6 +152,15 @@
                            AllowDuplicateMaskedServerCardIfFlagEnabled);
   FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest, DontDuplicateFullServerCard);
   FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest, DontDuplicateMaskedServerCard);
+  FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
+                           ImportFormData_AddressesDisabledOneCreditCard);
+  FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
+                           ImportFormData_AddressCreditCardDisabled);
+  FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
+                           ImportFormData_HiddenCreditCardFormAfterEntered);
+  FRIEND_TEST_ALL_PREFIXES(
+      FormDataImporterTest,
+      ImportFormData_HiddenCreditCardFormAfterEnteredWithExpOff);
   FRIEND_TEST_ALL_PREFIXES(
       FormDataImporterTest,
       ImportFormData_ImportCreditCardRecordType_FullServerCard);
@@ -179,10 +188,6 @@
       FormDataImporterTest,
       ImportFormData_SecondImportResetsCreditCardRecordType);
   FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
-                           ImportFormData_AddressesDisabledOneCreditCard);
-  FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
-                           ImportFormData_AddressCreditCardDisabled);
-  FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
                            ImportFormData_TwoAddressesOneCreditCard);
   FRIEND_TEST_ALL_PREFIXES(
       FormDataImporterTest,
diff --git a/components/autofill/core/browser/form_data_importer_unittest.cc b/components/autofill/core/browser/form_data_importer_unittest.cc
index 8e297de..a205459 100644
--- a/components/autofill/core/browser/form_data_importer_unittest.cc
+++ b/components/autofill/core/browser/form_data_importer_unittest.cc
@@ -2794,6 +2794,101 @@
   ASSERT_FALSE(imported_credit_card);
 }
 
+// Tests that a credit card form that is hidden after receiving input still
+// imports the card.
+TEST_F(FormDataImporterTest, ImportFormData_HiddenCreditCardFormAfterEntered) {
+  scoped_feature_list_.InitAndEnableFeature(
+      features::kAutofillImportNonFocusableCreditCardForms);
+
+  FormData form;
+  form.origin = GURL("https://wwww.foo.com");
+
+  FormFieldData field;
+
+  test::CreateTestFormField("Name on card:", "name_on_card", "Biggie Smalls",
+                            "text", &field);
+  field.is_focusable = false;
+  form.fields.push_back(field);
+  test::CreateTestFormField("Card Number:", "card_number", "4111111111111111",
+                            "text", &field);
+  field.is_focusable = false;
+  form.fields.push_back(field);
+  test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
+                            &field);
+  field.is_focusable = false;
+  form.fields.push_back(field);
+  test::CreateTestFormField("Exp Month:", "exp_month", "01", "text", &field);
+  field.is_focusable = false;
+  form.fields.push_back(field);
+  test::CreateTestFormField("Exp Year:", "exp_year", "2999", "text", &field);
+  field.is_focusable = false;
+  form.fields.push_back(field);
+
+  FormStructure form_structure(form);
+  form_structure.DetermineHeuristicTypes();
+  std::unique_ptr<CreditCard> imported_credit_card;
+  // Still returns true because the credit card import was successful.
+  EXPECT_TRUE(form_data_importer_->ImportFormData(
+      form_structure, /*profile_autofill_enabled=*/true,
+      /*credit_card_autofill_enabled=*/true,
+      /*should_return_local_card=*/false, &imported_credit_card));
+  ASSERT_TRUE(imported_credit_card);
+  personal_data_manager_->OnAcceptedLocalCreditCardSave(*imported_credit_card);
+
+  WaitForOnPersonalDataChanged();
+
+  // Test that the credit card has been saved.
+  CreditCard expected_card(base::GenerateGUID(), test::kEmptyOrigin);
+  test::SetCreditCardInfo(&expected_card, "Biggie Smalls", "4111111111111111",
+                          "01", "2999", "");
+  const std::vector<CreditCard*>& results =
+      personal_data_manager_->GetCreditCards();
+  ASSERT_EQ(1U, results.size());
+  EXPECT_EQ(0, expected_card.Compare(*results[0]));
+}
+
+// Tests that a credit card form that is hidden after receiving input does not
+// import the card when the experiment is off.
+TEST_F(FormDataImporterTest,
+       ImportFormData_HiddenCreditCardFormAfterEnteredWithExpOff) {
+  scoped_feature_list_.InitAndDisableFeature(
+      features::kAutofillImportNonFocusableCreditCardForms);
+
+  FormData form;
+  form.origin = GURL("https://wwww.foo.com");
+
+  FormFieldData field;
+
+  test::CreateTestFormField("Name on card:", "name_on_card", "Biggie Smalls",
+                            "text", &field);
+  field.is_focusable = false;
+  form.fields.push_back(field);
+  test::CreateTestFormField("Card Number:", "card_number", "4111111111111111",
+                            "text", &field);
+  field.is_focusable = false;
+  form.fields.push_back(field);
+  test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
+                            &field);
+  field.is_focusable = false;
+  form.fields.push_back(field);
+  test::CreateTestFormField("Exp Month:", "exp_month", "01", "text", &field);
+  field.is_focusable = false;
+  form.fields.push_back(field);
+  test::CreateTestFormField("Exp Year:", "exp_year", "2999", "text", &field);
+  field.is_focusable = false;
+  form.fields.push_back(field);
+
+  FormStructure form_structure(form);
+  form_structure.DetermineHeuristicTypes();
+  std::unique_ptr<CreditCard> imported_credit_card;
+  // Returns false because the credit card import was failed.
+  EXPECT_FALSE(form_data_importer_->ImportFormData(
+      form_structure, /*profile_autofill_enabled=*/true,
+      /*credit_card_autofill_enabled=*/true,
+      /*should_return_local_card=*/false, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
+}
+
 TEST_F(FormDataImporterTest, DontDuplicateFullServerCard) {
   EnableWalletCardImport();
 
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index aa2e7ca..fbe039a 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -129,6 +129,12 @@
 const base::Feature kAutofillGetPaymentsIdentityFromSync{
     "AutofillGetPaymentsIdentityFromSync", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// When enabled, a credit card form that is hidden after receiving input can
+// import the card.
+const base::Feature kAutofillImportNonFocusableCreditCardForms{
+    "AutofillImportNonFocusableCreditCardForms",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+
 // When enabled, autofill suggestions are displayed in the keyboard accessory
 // instead of the regular popup.
 const base::Feature kAutofillKeyboardAccessory{
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h
index 977b4bc..01e901d 100644
--- a/components/autofill/core/common/autofill_features.h
+++ b/components/autofill/core/common/autofill_features.h
@@ -43,6 +43,7 @@
 extern const base::Feature kAutofillEnforceMinRequiredFieldsForQuery;
 extern const base::Feature kAutofillEnforceMinRequiredFieldsForUpload;
 extern const base::Feature kAutofillGetPaymentsIdentityFromSync;
+extern const base::Feature kAutofillImportNonFocusableCreditCardForms;
 extern const base::Feature kAutofillKeyboardAccessory;
 extern const base::Feature kAutofillLocalCardMigrationShowFeedback;
 extern const base::Feature kAutofillManualFallback;
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index cc6f84c..dc7780f 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -31311,6 +31311,8 @@
   <int value="-741806604" label="DownloadsUi:disabled"/>
   <int value="-738957187" label="OmniboxUIExperimentSwapTitleAndUrl:disabled"/>
   <int value="-735084806" label="NewTabLoadingAnimation:enabled"/>
+  <int value="-734301625"
+      label="AutofillImportNonFocusableCreditCardForms:disabled"/>
   <int value="-731133967" label="AutofillSettingsCardTypeSplit:disabled"/>
   <int value="-727860269" label="WebAuthenticationBle:disabled"/>
   <int value="-726892130" label="AndroidMessagesIntegration:disabled"/>
@@ -31865,6 +31867,8 @@
   <int value="304901781" label="NewUsbBackend:enabled"/>
   <int value="306641800" label="AndroidSiteSettingsUIRefresh:disabled"/>
   <int value="307543404" label="disable-team-drives"/>
+  <int value="310143091"
+      label="AutofillImportNonFocusableCreditCardForms:enabled"/>
   <int value="313253630" label="AutofillRefreshStyleAndroid:enabled"/>
   <int value="313303258" label="WebPaymentsModifiers:disabled"/>
   <int value="316182183" label="MediaDocumentDownloadButton:disabled"/>