[Autofill] [Butter] Add No thanks button to save card dialog

This CL patched another CL by jsaul@
https://chromium-review.googlesource.com/c/chromium/src/+/1334834

1) Added No thanks button as required by legal.
2) Changed the title to better explain its usage.

Uploaded screenshot in the bug comment#4.

Bug: 905393
Change-Id: Idc6e2e89a9cad9d4f5530ea4d4a1b2731feeff5e
Reviewed-on: https://chromium-review.googlesource.com/c/1343281
Reviewed-by: Fabio Tirelo <[email protected]>
Reviewed-by: Elly Fong-Jones <[email protected]>
Reviewed-by: Evan Stade <[email protected]>
Commit-Queue: Fabio Tirelo <[email protected]>
Cr-Commit-Position: refs/heads/master@{#610237}
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index b2b8ebd..237ddbf86 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3020,6 +3020,12 @@
      kOsDesktop,
      FEATURE_VALUE_TYPE(
          autofill::features::kAutofillSaveCardDialogUnlabeledExpirationDate)},
+    {"enable-autofill-save-card-improved-user-consent",
+     flag_descriptions::kEnableAutofillSaveCardImprovedUserConsentName,
+     flag_descriptions::kEnableAutofillSaveCardImprovedUserConsentDescription,
+     kOsDesktop,
+     FEATURE_VALUE_TYPE(
+         autofill::features::kAutofillSaveCardImprovedUserConsent)},
     {"enable-autofill-save-card-sign-in-after-local-save",
      flag_descriptions::kEnableAutofillSaveCardSignInAfterLocalSaveName,
      flag_descriptions::kEnableAutofillSaveCardSignInAfterLocalSaveDescription,
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 01e929e..b6d5f1f 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -842,6 +842,11 @@
     "expiry_milestone": 76
   },
   {
+    "name": "enable-autofill-save-card-improved-user-consent",
+    "owners": [ "[email protected]" ],
+    "expiry_milestone": 73
+  },
+  {
     "name": "enable-autofill-save-card-sign-in-after-local-save",
     // "owners": [ "your-team" ],
     "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 13b334a..7cab0c9 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -400,6 +400,12 @@
     "If enabled, expiration dates on the save card dialog (both local and "
     "upstream) are shown without an 'Exp:' label.";
 
+const char kEnableAutofillSaveCardImprovedUserConsentName[] =
+    "Use updated UI for credit card save bubbles";
+const char kEnableAutofillSaveCardImprovedUserConsentDescription[] =
+    "If enabled, adds a [No thanks] button to credit card save bubbles and "
+    "updates their title headers.";
+
 const char kEnableAutofillSaveCardSignInAfterLocalSaveName[] =
     "Show Sign-In/Sync promo after saving a card locally";
 const char kEnableAutofillSaveCardSignInAfterLocalSaveDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index d3273937..7ccefe3 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -259,6 +259,9 @@
 extern const char kEnableAutofillLocalCardMigrationShowFeedbackName[];
 extern const char kEnableAutofillLocalCardMigrationShowFeedbackDescription[];
 
+extern const char kEnableAutofillSaveCardImprovedUserConsentName[];
+extern const char kEnableAutofillSaveCardImprovedUserConsentDescription[];
+
 extern const char kEnableAutofillSaveCreditCardUsesStrikeSystemName[];
 extern const char kEnableAutofillSaveCreditCardUsesStrikeSystemDescription[];
 
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc
index e01c653..2007f01 100644
--- a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc
+++ b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc
@@ -215,7 +215,10 @@
           IDS_AUTOFILL_SAVE_CARD_PROMPT_TITLE_LOCAL);
     case BubbleType::UPLOAD_SAVE:
       return l10n_util::GetStringUTF16(
-          IDS_AUTOFILL_SAVE_CARD_PROMPT_TITLE_TO_CLOUD_V3);
+          base::FeatureList::IsEnabled(
+              features::kAutofillSaveCardImprovedUserConsent)
+              ? IDS_AUTOFILL_SAVE_CARD_PROMPT_TITLE_TO_CLOUD_V4
+              : IDS_AUTOFILL_SAVE_CARD_PROMPT_TITLE_TO_CLOUD_V3);
     case BubbleType::SIGN_IN_PROMO:
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
       if (AccountConsistencyModeManager::IsDiceEnabledForProfile(
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
index af2355e..798b950 100644
--- a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
+++ b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
@@ -107,10 +107,6 @@
   return true;
 }
 
-int SaveCardBubbleViews::GetDialogButtons() const {
-  return ui::DIALOG_BUTTON_OK;
-}
-
 gfx::Size SaveCardBubbleViews::CalculatePreferredSize() const {
   const int width = ChromeLayoutProvider::Get()->GetDistanceMetric(
                         DISTANCE_BUBBLE_PREFERRED_WIDTH) -
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views.h b/chrome/browser/ui/views/autofill/save_card_bubble_views.h
index 692015bb..db3f89cc 100644
--- a/chrome/browser/ui/views/autofill/save_card_bubble_views.h
+++ b/chrome/browser/ui/views/autofill/save_card_bubble_views.h
@@ -44,7 +44,6 @@
   bool Accept() override;
   bool Cancel() override;
   bool Close() override;
-  int GetDialogButtons() const override;
 
   // views::View:
   gfx::Size CalculatePreferredSize() const override;
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc
index e08a65d..2ff82fb 100644
--- a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc
+++ b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc
@@ -124,6 +124,39 @@
                    "Signin_Impression_FromSaveCardBubble"));
 }
 
+// Tests the local save bubble. Ensures that clicking the [No thanks] button
+// successfully causes the bubble to go away.
+IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
+                       Local_ClickingNoThanksClosesBubble) {
+  // Enable the updated UI.
+  scoped_feature_list_.InitAndEnableFeature(
+      features::kAutofillSaveCardImprovedUserConsent);
+
+  // Set up the Payments RPC.
+  SetUploadDetailsRpcPaymentsDeclines();
+
+  // Submitting the form and having Payments decline offering to save should
+  // show the local save bubble.
+  // (Must wait for response from Payments before accessing the controller.)
+  ResetEventWaiterForSequence(
+      {DialogEvent::REQUESTED_UPLOAD_SAVE,
+       DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE,
+       DialogEvent::OFFERED_LOCAL_SAVE});
+  FillAndSubmitForm();
+  WaitForObservedEvent();
+  EXPECT_TRUE(
+      FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_LOCAL)->visible());
+
+  // Clicking [No thanks] should cancel and close it.
+  base::HistogramTester histogram_tester;
+  ClickOnCancelButton();
+
+  // UMA should have recorded bubble rejection.
+  histogram_tester.ExpectUniqueSample(
+      "Autofill.SaveCreditCardPrompt.Local.FirstShow",
+      AutofillMetrics::SAVE_CARD_PROMPT_END_DENIED, 1);
+}
+
 // Tests the sign in promo bubble. Ensures that clicking the [Save] button
 // on the local save bubble successfully causes the sign in promo to show.
 #if !defined(OS_CHROMEOS)
@@ -579,10 +612,14 @@
 }
 #endif
 
-// Tests the local save bubble. Ensures that the Harmony version of the bubble
-// does not have a [No thanks] button (it has an [X] Close button instead.)
+// Tests the local save bubble. Ensures that the bubble does not have a
+// [No thanks] button (it has an [X] Close button instead.)
 IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
                        Local_ShouldNotHaveNoThanksButton) {
+  // Disable the updated UI.
+  scoped_feature_list_.InitAndDisableFeature(
+      features::kAutofillSaveCardImprovedUserConsent);
+
   // Set up the Payments RPC.
   SetUploadDetailsRpcPaymentsDeclines();
 
@@ -671,10 +708,46 @@
       AutofillMetrics::SAVE_CARD_PROMPT_END_ACCEPTED, 1);
 }
 
-// Tests the upload save bubble. Ensures that the Harmony version of the bubble
-// does not have a [No thanks] button (it has an [X] Close button instead.)
+// Tests the upload save bubble. Ensures that clicking the [No thanks] button
+// successfully causes the bubble to go away.
+IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
+                       Upload_ClickingNoThanksClosesBubble) {
+  // Enable the updated UI.
+  scoped_feature_list_.InitAndEnableFeature(
+      features::kAutofillSaveCardImprovedUserConsent);
+
+  // Set up the Payments RPC.
+  SetUploadDetailsRpcPaymentsAccepts();
+
+  // Submitting the form should show the upload save bubble and legal footer.
+  // (Must wait for response from Payments before accessing the controller.)
+  ResetEventWaiterForSequence(
+      {DialogEvent::REQUESTED_UPLOAD_SAVE,
+       DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE});
+  FillAndSubmitForm();
+  WaitForObservedEvent();
+  EXPECT_TRUE(
+      FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_UPLOAD)->visible());
+  EXPECT_TRUE(FindViewInBubbleById(DialogViewId::FOOTNOTE_VIEW)->visible());
+
+  // Clicking [No thanks] should cancel and close it.
+  base::HistogramTester histogram_tester;
+  ClickOnCancelButton();
+
+  // UMA should have recorded bubble rejection.
+  histogram_tester.ExpectUniqueSample(
+      "Autofill.SaveCreditCardPrompt.Upload.FirstShow",
+      AutofillMetrics::SAVE_CARD_PROMPT_END_DENIED, 1);
+}
+
+// Tests the upload save bubble. Ensures that the bubble does not have a
+// [No thanks] button (it has an [X] Close button instead.)
 IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
                        Upload_ShouldNotHaveNoThanksButton) {
+  // Disable the updated UI.
+  scoped_feature_list_.InitAndDisableFeature(
+      features::kAutofillSaveCardImprovedUserConsent);
+
   // Set up the Payments RPC.
   SetUploadDetailsRpcPaymentsAccepts();
 
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.cc
index 9e51c2e..402585d 100644
--- a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.cc
+++ b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.cc
@@ -489,6 +489,14 @@
   return specified_view;
 }
 
+void SaveCardBubbleViewsBrowserTestBase::ClickOnCancelButton() {
+  SaveCardBubbleViews* save_card_bubble_views = GetSaveCardBubbleViews();
+  DCHECK(save_card_bubble_views);
+  ResetEventWaiterForSequence({DialogEvent::BUBBLE_CLOSED});
+  ClickOnDialogViewWithIdAndWait(DialogViewId::CANCEL_BUTTON);
+  DCHECK(!GetSaveCardBubbleViews());
+}
+
 void SaveCardBubbleViewsBrowserTestBase::ClickOnCloseButton() {
   SaveCardBubbleViews* save_card_bubble_views = GetSaveCardBubbleViews();
   DCHECK(save_card_bubble_views);
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h
index e1d1bde..cd60775 100644
--- a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h
+++ b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h
@@ -125,6 +125,10 @@
   views::View* FindViewInBubbleById(DialogViewId view_id);
 
   // Assert that there is a SaveCardBubbleViews bubble open, then click on the
+  // [No thanks] button.
+  void ClickOnCancelButton();
+
+  // Assert that there is a SaveCardBubbleViews bubble open, then click on the
   // [X] button.
   void ClickOnCloseButton();
 
diff --git a/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.cc b/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.cc
index bd6452a..0408eb0 100644
--- a/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.cc
+++ b/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.cc
@@ -83,6 +83,13 @@
   return true;
 }
 
+int SaveCardOfferBubbleViews::GetDialogButtons() const {
+  return base::FeatureList::IsEnabled(
+             features::kAutofillSaveCardImprovedUserConsent)
+             ? ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL
+             : ui::DIALOG_BUTTON_OK;
+}
+
 base::string16 SaveCardOfferBubbleViews::GetDialogButtonLabel(
     ui::DialogButton button) const {
   return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK
diff --git a/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.h b/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.h
index 9d2c5fd..d3235d7 100644
--- a/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.h
+++ b/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.h
@@ -38,6 +38,7 @@
   views::View* CreateFootnoteView() override;
   bool Accept() override;
   base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
+  int GetDialogButtons() const override;
   bool IsDialogButtonEnabled(ui::DialogButton button) const override;
 
   // views::StyledLabelListener: