| 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..04dab9198c924e89e4b8d9bb52de96381dd807e2 100644
|
| --- a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
|
| +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
|
| @@ -61,8 +61,6 @@ SaveCardBubbleViews::SaveCardBubbleViews(views::View* anchor_view,
|
| chrome::RecordDialogCreation(chrome::DialogIdentifier::SAVE_CARD);
|
| }
|
|
|
| -SaveCardBubbleViews::~SaveCardBubbleViews() {}
|
| -
|
| void SaveCardBubbleViews::Show(DisplayReason reason) {
|
| ShowForReason(reason);
|
| }
|
| @@ -73,6 +71,9 @@ void SaveCardBubbleViews::Hide() {
|
| }
|
|
|
| views::View* SaveCardBubbleViews::CreateExtraView() {
|
| + if (GetCurrentFlowStep() != LOCAL_SAVE_ONLY_STEP)
|
| + return nullptr;
|
| + // Learn More link is only shown on local save bubble.
|
| DCHECK(!learn_more_link_);
|
| learn_more_link_ = new views::Link(l10n_util::GetStringUTF16(IDS_LEARN_MORE));
|
| learn_more_link_->SetUnderline(false);
|
| @@ -85,14 +86,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 +111,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 +147,57 @@ bool SaveCardBubbleViews::Close() {
|
| return true;
|
| }
|
|
|
| +int SaveCardBubbleViews::GetDialogButtons() const {
|
| + if (GetCurrentFlowStep() == LOCAL_SAVE_ONLY_STEP)
|
| + return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL;
|
| + // For upload save, 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);
|
| + 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 should have a [No thanks] button, but Upload save should surface
|
| + // the top-right [X] close button instead.
|
| + return GetCurrentFlowStep() != LOCAL_SAVE_ONLY_STEP;
|
| +}
|
| +
|
| base::string16 SaveCardBubbleViews::GetWindowTitle() const {
|
| return controller_ ? controller_->GetWindowTitle() : base::string16();
|
| }
|
| @@ -184,6 +239,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 +274,15 @@ 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.
|
| + base::string16 explanation = controller_->GetExplanatoryMessage();
|
| + if (!explanation.empty()) {
|
| + 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,67 +301,51 @@ 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()));
|
| -
|
| - // Optionally add label that will contain an explanation for upload.
|
| - base::string16 explanation = controller_->GetExplanatoryMessage();
|
| - if (!explanation.empty()) {
|
| - views::Label* explanation_label = new views::Label(explanation);
|
| - explanation_label->SetMultiLine(true);
|
| - explanation_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| - view->AddChildView(explanation_label);
|
| - }
|
| + new views::Label(card.NetworkAndLastFourDigits()));
|
|
|
| return view;
|
| }
|
|
|
| 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();
|
|
|