| Index: chrome/browser/ui/views/autofill/save_card_bubble_views.cc
|
| 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 c418d39aa566a940f29fa50eefe25ec10b9027ed..172c67a711a0a920f86785cb99fa87a6f3cccbbc 100644
|
| --- a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
|
| +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
|
| @@ -12,6 +12,7 @@
|
| #include "chrome/browser/ui/browser_dialogs.h"
|
| #include "chrome/browser/ui/views/autofill/view_util.h"
|
| #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
|
| +#include "components/autofill/core/browser/autofill_experiments.h"
|
| #include "components/autofill/core/browser/credit_card.h"
|
| #include "components/autofill/core/browser/legal_message_line.h"
|
| #include "components/autofill/core/browser/ui/save_card_bubble_controller.h"
|
| @@ -61,8 +62,6 @@ SaveCardBubbleViews::SaveCardBubbleViews(views::View* anchor_view,
|
| chrome::RecordDialogCreation(chrome::DialogIdentifier::SAVE_CARD);
|
| }
|
|
|
| -SaveCardBubbleViews::~SaveCardBubbleViews() {}
|
| -
|
| void SaveCardBubbleViews::Show(DisplayReason reason) {
|
| ShowForReason(reason);
|
| }
|
| @@ -73,6 +72,11 @@ void SaveCardBubbleViews::Hide() {
|
| }
|
|
|
| views::View* SaveCardBubbleViews::CreateExtraView() {
|
| + if (GetCurrentFlowStep() != LOCAL_SAVE_ONLY_STEP &&
|
| + IsAutofillUpstreamShowNewUiExperimentEnabled())
|
| + return nullptr;
|
| + // Learn More link is only shown on local save bubble or when the new UI
|
| + // experiment is disabled.
|
| DCHECK(!learn_more_link_);
|
| learn_more_link_ = new views::Link(l10n_util::GetStringUTF16(IDS_LEARN_MORE));
|
| learn_more_link_->SetUnderline(false);
|
| @@ -85,14 +89,22 @@ views::View* SaveCardBubbleViews::CreateFootnoteView() {
|
| return nullptr;
|
|
|
| // Use BoxLayout to provide insets around the label.
|
| - View* view = new View();
|
| - view->SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical));
|
| + footnote_view_ = new View();
|
| + footnote_view_->SetLayoutManager(
|
| + new views::BoxLayout(views::BoxLayout::kVertical));
|
|
|
| // Add a StyledLabel for each line of the legal message.
|
| - for (const LegalMessageLine& line : controller_->GetLegalMessageLines())
|
| - view->AddChildView(CreateLegalMessageLineLabel(line, this).release());
|
| + for (const LegalMessageLine& line : controller_->GetLegalMessageLines()) {
|
| + footnote_view_->AddChildView(
|
| + CreateLegalMessageLineLabel(line, this).release());
|
| + }
|
|
|
| - return view;
|
| + // If on the first step of the 2-step upload flow, hide the footer area until
|
| + // it's time to actually accept the dialog and ToS.
|
| + if (GetCurrentFlowStep() == UPLOAD_SAVE_CVC_FIX_FLOW_STEP_1_OFFER_UPLOAD)
|
| + footnote_view_->SetVisible(false);
|
| +
|
| + return footnote_view_;
|
| }
|
|
|
| bool SaveCardBubbleViews::Accept() {
|
| @@ -102,12 +114,18 @@ bool SaveCardBubbleViews::Accept() {
|
| // and that if it *does* have 2, it's because CVC is being requested.
|
| DCHECK_LE(view_stack_->size(), 2U);
|
| DCHECK(view_stack_->size() == 1 || controller_->ShouldRequestCvcFromUser());
|
| - if (controller_->ShouldRequestCvcFromUser() && view_stack_->size() == 1) {
|
| + if (GetCurrentFlowStep() == UPLOAD_SAVE_CVC_FIX_FLOW_STEP_1_OFFER_UPLOAD) {
|
| // If user accepted upload but more info is needed, push the next view onto
|
| - // the stack.
|
| + // the stack and update the bubble.
|
| + DCHECK(controller_);
|
| + controller_->SetShowUploadConfirmTitle(true);
|
| + GetWidget()->UpdateWindowTitle();
|
| view_stack_->Push(CreateRequestCvcView(), /*animate=*/true);
|
| // Disable the Save button until a valid CVC is entered:
|
| GetDialogClientView()->UpdateDialogButtons();
|
| + // Make the legal messaging footer appear:
|
| + DCHECK(footnote_view_);
|
| + footnote_view_->SetVisible(true);
|
| // Resize the bubble if it's grown larger:
|
| SizeToContents();
|
| return false;
|
| @@ -132,17 +150,67 @@ bool SaveCardBubbleViews::Close() {
|
| return true;
|
| }
|
|
|
| +int SaveCardBubbleViews::GetDialogButtons() const {
|
| + if (GetCurrentFlowStep() == LOCAL_SAVE_ONLY_STEP ||
|
| + !IsAutofillUpstreamShowNewUiExperimentEnabled())
|
| + return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL;
|
| + // For upload save when the new UI experiment is enabled, don't show the
|
| + // [No thanks] cancel option; use the top-right [X] close button for that.
|
| + return ui::DIALOG_BUTTON_OK;
|
| +}
|
| +
|
| base::string16 SaveCardBubbleViews::GetDialogButtonLabel(
|
| ui::DialogButton button) const {
|
| - return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK
|
| - ? IDS_AUTOFILL_SAVE_CARD_PROMPT_ACCEPT
|
| - : IDS_NO_THANKS);
|
| + if (!IsAutofillUpstreamShowNewUiExperimentEnabled()) {
|
| + // New UI experiment disabled:
|
| + return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK
|
| + ? IDS_AUTOFILL_SAVE_CARD_PROMPT_ACCEPT
|
| + : IDS_NO_THANKS);
|
| + }
|
| + // New UI experiment enabled:
|
| + switch (GetCurrentFlowStep()) {
|
| + // Local save has two buttons:
|
| + case LOCAL_SAVE_ONLY_STEP:
|
| + return l10n_util::GetStringUTF16(
|
| + button == ui::DIALOG_BUTTON_OK ? IDS_AUTOFILL_SAVE_CARD_PROMPT_ACCEPT
|
| + : IDS_NO_THANKS);
|
| + // Upload save has one button but it can say three different things:
|
| + case UPLOAD_SAVE_ONLY_STEP:
|
| + DCHECK(button == ui::DIALOG_BUTTON_OK);
|
| + return l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_CARD_PROMPT_ACCEPT);
|
| + case UPLOAD_SAVE_CVC_FIX_FLOW_STEP_1_OFFER_UPLOAD:
|
| + DCHECK(button == ui::DIALOG_BUTTON_OK);
|
| + return l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_CARD_PROMPT_NEXT);
|
| + case UPLOAD_SAVE_CVC_FIX_FLOW_STEP_2_REQUEST_CVC:
|
| + DCHECK(button == ui::DIALOG_BUTTON_OK);
|
| + return l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_CARD_PROMPT_CONFIRM);
|
| + default:
|
| + NOTREACHED();
|
| + return base::string16();
|
| + }
|
| +}
|
| +
|
| +bool SaveCardBubbleViews::IsDialogButtonEnabled(ui::DialogButton button) const {
|
| + if (button == ui::DIALOG_BUTTON_CANCEL)
|
| + return true;
|
| +
|
| + DCHECK_EQ(ui::DIALOG_BUTTON_OK, button);
|
| + return !cvc_textfield_ ||
|
| + controller_->InputCvcIsValid(cvc_textfield_->text());
|
| }
|
|
|
| gfx::Size SaveCardBubbleViews::CalculatePreferredSize() const {
|
| return gfx::Size(kBubbleWidth, GetHeightForWidth(kBubbleWidth));
|
| }
|
|
|
| +bool SaveCardBubbleViews::ShouldShowCloseButton() const {
|
| + // Local save and Upload save on the old UI should have a [No thanks] button,
|
| + // but Upload save on the new UI should surface the top-right [X] close button
|
| + // instead.
|
| + return GetCurrentFlowStep() != LOCAL_SAVE_ONLY_STEP &&
|
| + IsAutofillUpstreamShowNewUiExperimentEnabled();
|
| +}
|
| +
|
| base::string16 SaveCardBubbleViews::GetWindowTitle() const {
|
| return controller_ ? controller_->GetWindowTitle() : base::string16();
|
| }
|
| @@ -184,6 +252,32 @@ void SaveCardBubbleViews::StyledLabelLinkClicked(views::StyledLabel* label,
|
| NOTREACHED();
|
| }
|
|
|
| +void SaveCardBubbleViews::ContentsChanged(views::Textfield* sender,
|
| + const base::string16& new_contents) {
|
| + DCHECK_EQ(cvc_textfield_, sender);
|
| + GetDialogClientView()->UpdateDialogButtons();
|
| +}
|
| +
|
| +SaveCardBubbleViews::~SaveCardBubbleViews() {}
|
| +
|
| +SaveCardBubbleViews::CurrentFlowStep SaveCardBubbleViews::GetCurrentFlowStep()
|
| + const {
|
| + // No legal messages means this is not upload save.
|
| + if (controller_->GetLegalMessageLines().empty())
|
| + return LOCAL_SAVE_ONLY_STEP;
|
| + // If we're not requesting CVC, this is the only step on the upload path.
|
| + if (!controller_->ShouldRequestCvcFromUser())
|
| + return UPLOAD_SAVE_ONLY_STEP;
|
| + // Must be on the CVC fix flow on the upload path.
|
| + if (view_stack_->size() == 1)
|
| + return UPLOAD_SAVE_CVC_FIX_FLOW_STEP_1_OFFER_UPLOAD;
|
| + if (view_stack_->size() == 2)
|
| + return UPLOAD_SAVE_CVC_FIX_FLOW_STEP_2_REQUEST_CVC;
|
| + // CVC fix flow should never have more than 3 views on the stack.
|
| + NOTREACHED();
|
| + return UNKNOWN_STEP;
|
| +}
|
| +
|
| // Create view containing everything except for the footnote.
|
| std::unique_ptr<views::View> SaveCardBubbleViews::CreateMainContentView() {
|
| auto view = base::MakeUnique<views::View>();
|
| @@ -193,6 +287,16 @@ std::unique_ptr<views::View> SaveCardBubbleViews::CreateMainContentView() {
|
| views::BoxLayout::kVertical, gfx::Insets(),
|
| provider->GetDistanceMetric(views::DISTANCE_UNRELATED_CONTROL_VERTICAL)));
|
|
|
| + // If applicable, add the upload explanation label. Appears above the card
|
| + // info when new UI experiment is enabled.
|
| + base::string16 explanation = controller_->GetExplanatoryMessage();
|
| + if (!explanation.empty() && IsAutofillUpstreamShowNewUiExperimentEnabled()) {
|
| + views::Label* explanation_label = new views::Label(explanation);
|
| + explanation_label->SetMultiLine(true);
|
| + explanation_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| + view->AddChildView(explanation_label);
|
| + }
|
| +
|
| // Add the card type icon, last four digits and expiration date.
|
| views::View* description_view = new views::View();
|
| description_view->SetLayoutManager(new views::BoxLayout(
|
| @@ -211,14 +315,21 @@ std::unique_ptr<views::View> SaveCardBubbleViews::CreateMainContentView() {
|
| views::CreateSolidBorder(1, SkColorSetA(SK_ColorBLACK, 10)));
|
| description_view->AddChildView(card_type_icon);
|
|
|
| - description_view->AddChildView(new views::Label(
|
| - base::string16(kMidlineEllipsis) + card.LastFourDigits()));
|
| - description_view->AddChildView(
|
| - new views::Label(card.AbbreviatedExpirationDateForDisplay()));
|
| + // Old UI shows last four digits and expiration. New UI shows network and
|
| + // last four digits, but no expiration.
|
| + if (IsAutofillUpstreamShowNewUiExperimentEnabled()) {
|
| + description_view->AddChildView(
|
| + new views::Label(card.NetworkAndLastFourDigits()));
|
| + } else {
|
| + description_view->AddChildView(new views::Label(
|
| + base::string16(kMidlineEllipsis) + card.LastFourDigits()));
|
| + description_view->AddChildView(
|
| + new views::Label(card.AbbreviatedExpirationDateForDisplay()));
|
| + }
|
|
|
| - // Optionally add label that will contain an explanation for upload.
|
| - base::string16 explanation = controller_->GetExplanatoryMessage();
|
| - if (!explanation.empty()) {
|
| + // If applicable, add the upload explanation label. Appears below the card
|
| + // info when new UI experiment is disabled.
|
| + if (!explanation.empty() && !IsAutofillUpstreamShowNewUiExperimentEnabled()) {
|
| views::Label* explanation_label = new views::Label(explanation);
|
| explanation_label->SetMultiLine(true);
|
| explanation_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| @@ -230,48 +341,43 @@ std::unique_ptr<views::View> SaveCardBubbleViews::CreateMainContentView() {
|
|
|
| std::unique_ptr<views::View> SaveCardBubbleViews::CreateRequestCvcView() {
|
| auto request_cvc_view = base::MakeUnique<views::View>();
|
| + ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
|
| +
|
| + request_cvc_view->SetLayoutManager(new views::BoxLayout(
|
| + views::BoxLayout::kVertical, gfx::Insets(),
|
| + provider->GetDistanceMetric(views::DISTANCE_UNRELATED_CONTROL_VERTICAL)));
|
| request_cvc_view->SetBackground(views::CreateThemedSolidBackground(
|
| request_cvc_view.get(), ui::NativeTheme::kColorId_BubbleBackground));
|
| - views::BoxLayout* layout =
|
| - new views::BoxLayout(views::BoxLayout::kHorizontal, gfx::Insets(),
|
| - ChromeLayoutProvider::Get()->GetDistanceMetric(
|
| - views::DISTANCE_RELATED_BUTTON_HORIZONTAL));
|
| +
|
| + views::Label* explanation_label = new views::Label(l10n_util::GetStringUTF16(
|
| + IDS_AUTOFILL_SAVE_CARD_PROMPT_ENTER_CVC_EXPLANATION));
|
| + explanation_label->SetMultiLine(true);
|
| + explanation_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| + request_cvc_view->AddChildView(explanation_label);
|
| +
|
| + views::View* cvc_entry_view = new views::View();
|
| + views::BoxLayout* layout = new views::BoxLayout(
|
| + views::BoxLayout::kHorizontal, gfx::Insets(),
|
| + provider->GetDistanceMetric(views::DISTANCE_RELATED_BUTTON_HORIZONTAL));
|
| layout->set_cross_axis_alignment(
|
| views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
|
| - request_cvc_view->SetLayoutManager(layout);
|
| + cvc_entry_view->SetLayoutManager(layout);
|
|
|
| DCHECK(!cvc_textfield_);
|
| cvc_textfield_ = CreateCvcTextfield();
|
| cvc_textfield_->set_controller(this);
|
| - request_cvc_view->AddChildView(cvc_textfield_);
|
| + cvc_entry_view->AddChildView(cvc_textfield_);
|
|
|
| views::ImageView* cvc_image = new views::ImageView();
|
| ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| cvc_image->SetImage(
|
| rb.GetImageSkiaNamed(controller_->GetCvcImageResourceId()));
|
| - request_cvc_view->AddChildView(cvc_image);
|
| -
|
| - request_cvc_view->AddChildView(new views::Label(
|
| - l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_CARD_PROMPT_ENTER_CVC)));
|
| + cvc_entry_view->AddChildView(cvc_image);
|
|
|
| + request_cvc_view->AddChildView(cvc_entry_view);
|
| return request_cvc_view;
|
| }
|
|
|
| -bool SaveCardBubbleViews::IsDialogButtonEnabled(ui::DialogButton button) const {
|
| - if (button == ui::DIALOG_BUTTON_CANCEL)
|
| - return true;
|
| -
|
| - DCHECK_EQ(ui::DIALOG_BUTTON_OK, button);
|
| - return !cvc_textfield_ ||
|
| - controller_->InputCvcIsValid(cvc_textfield_->text());
|
| -}
|
| -
|
| -void SaveCardBubbleViews::ContentsChanged(views::Textfield* sender,
|
| - const base::string16& new_contents) {
|
| - DCHECK_EQ(cvc_textfield_, sender);
|
| - GetDialogClientView()->UpdateDialogButtons();
|
| -}
|
| -
|
| void SaveCardBubbleViews::Init() {
|
| SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical));
|
| view_stack_ = new ViewStack();
|
|
|