Chromium Code Reviews| 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..8f0dcd7d87c2b9a157f746d8610ea937e2776d25 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 disabled, don't show the |
|
Mathieu
2017/08/09 00:17:23
it seems like you will be here if the experiment i
Jared Saul
2017/08/09 00:24:19
Wow, good catch! Done, thanks.
|
| + // [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(); |