blob: 78c721baabe81cfa2ef6f99bfa6aa5294288aa4d [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/autofill/save_card_offer_bubble_views.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/views/autofill/dialog_view_ids.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/chrome_typography.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_metrics.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"
#include "components/autofill/core/common/autofill_features.h"
#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/material_design/material_design_controller.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/border.h"
#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/bubble/tooltip_icon.h"
#include "ui/views/controls/button/blue_button.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/separator.h"
#include "ui/views/controls/styled_label.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/style/typography.h"
#include "ui/views/window/dialog_client_view.h"
namespace autofill {
namespace {
const int kTooltipIconSize = 12;
} // namespace
SaveCardOfferBubbleViews::SaveCardOfferBubbleViews(
views::View* anchor_view,
const gfx::Point& anchor_point,
content::WebContents* web_contents,
SaveCardBubbleController* controller)
: SaveCardBubbleViews(anchor_view, anchor_point, web_contents, controller),
web_contents_(web_contents) {}
views::View* SaveCardOfferBubbleViews::CreateFootnoteView() {
if (controller()->GetLegalMessageLines().empty())
return nullptr;
footnote_view_ =
new LegalMessageView(controller()->GetLegalMessageLines(), this);
footnote_view_->set_id(DialogViewId::FOOTNOTE_VIEW);
SetFootnoteViewForTesting(footnote_view_);
return footnote_view_;
}
bool SaveCardOfferBubbleViews::Accept() {
if (controller())
controller()->OnSaveButton(cardholder_name_textfield_
? cardholder_name_textfield_->text()
: base::string16());
return true;
}
base::string16 SaveCardOfferBubbleViews::GetDialogButtonLabel(
ui::DialogButton button) const {
return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK
? IDS_AUTOFILL_SAVE_CARD_PROMPT_ACCEPT
: IDS_NO_THANKS);
}
bool SaveCardOfferBubbleViews::IsDialogButtonEnabled(
ui::DialogButton button) const {
if (button == ui::DIALOG_BUTTON_CANCEL)
return true;
DCHECK_EQ(ui::DIALOG_BUTTON_OK, button);
if (cardholder_name_textfield_) {
// If requesting the user confirm the name, it cannot be blank.
base::string16 trimmed_text;
base::TrimWhitespace(cardholder_name_textfield_->text(), base::TRIM_ALL,
&trimmed_text);
return !trimmed_text.empty();
}
return true;
}
void SaveCardOfferBubbleViews::StyledLabelLinkClicked(views::StyledLabel* label,
const gfx::Range& range,
int event_flags) {
if (!controller())
return;
footnote_view_->OnLinkClicked(label, range, web_contents_);
}
void SaveCardOfferBubbleViews::ContentsChanged(
views::Textfield* sender,
const base::string16& new_contents) {
DCHECK_EQ(cardholder_name_textfield_, sender);
DialogModelChanged();
}
SaveCardOfferBubbleViews::~SaveCardOfferBubbleViews() {}
std::unique_ptr<views::View> SaveCardOfferBubbleViews::CreateMainContentView() {
std::unique_ptr<views::View> view =
SaveCardBubbleViews::CreateMainContentView();
ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
view->set_id(controller()->IsUploadSave()
? DialogViewId::MAIN_CONTENT_VIEW_UPLOAD
: DialogViewId::MAIN_CONTENT_VIEW_LOCAL);
// If necessary, add the cardholder name label and textfield to the upload
// save dialog.
if (controller()->ShouldRequestNameFromUser()) {
std::unique_ptr<views::View> cardholder_name_label_row =
std::make_unique<views::View>();
// Set up cardholder name label.
// TODO(jsaul): DISTANCE_RELATED_BUTTON_HORIZONTAL isn't the right choice
// here, but DISTANCE_RELATED_CONTROL_HORIZONTAL gives too much
// padding. Make a new Harmony DistanceMetric?
cardholder_name_label_row->SetLayoutManager(
std::make_unique<views::BoxLayout>(
views::BoxLayout::kHorizontal, gfx::Insets(),
provider->GetDistanceMetric(
views::DISTANCE_RELATED_BUTTON_HORIZONTAL)));
std::unique_ptr<views::Label> cardholder_name_label =
std::make_unique<views::Label>(
l10n_util::GetStringUTF16(
IDS_AUTOFILL_SAVE_CARD_PROMPT_CARDHOLDER_NAME),
CONTEXT_BODY_TEXT_LARGE, ChromeTextStyle::STYLE_SECONDARY);
cardholder_name_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
cardholder_name_label_row->AddChildView(cardholder_name_label.release());
// Prepare the prefilled cardholder name.
base::string16 prefilled_name;
if (!features::
IsAutofillUpstreamBlankCardholderNameFieldExperimentEnabled()) {
prefilled_name =
base::UTF8ToUTF16(controller()->GetAccountInfo().full_name);
}
// Set up cardholder name label tooltip ONLY if the cardholder name
// textfield will be prefilled.
if (!prefilled_name.empty()) {
std::unique_ptr<views::TooltipIcon> cardholder_name_tooltip =
std::make_unique<views::TooltipIcon>(
l10n_util::GetStringUTF16(
IDS_AUTOFILL_SAVE_CARD_PROMPT_CARDHOLDER_NAME_TOOLTIP),
kTooltipIconSize);
cardholder_name_tooltip->set_anchor_point_arrow(
views::BubbleBorder::Arrow::TOP_LEFT);
cardholder_name_tooltip->set_id(DialogViewId::CARDHOLDER_NAME_TOOLTIP);
cardholder_name_label_row->AddChildView(
cardholder_name_tooltip.release());
}
// Set up cardholder name textfield.
DCHECK(!cardholder_name_textfield_);
cardholder_name_textfield_ = new views::Textfield();
cardholder_name_textfield_->set_controller(this);
cardholder_name_textfield_->set_id(DialogViewId::CARDHOLDER_NAME_TEXTFIELD);
cardholder_name_textfield_->SetAccessibleName(l10n_util::GetStringUTF16(
IDS_AUTOFILL_SAVE_CARD_PROMPT_CARDHOLDER_NAME));
cardholder_name_textfield_->SetTextInputType(
ui::TextInputType::TEXT_INPUT_TYPE_TEXT);
cardholder_name_textfield_->SetText(prefilled_name);
AutofillMetrics::LogSaveCardCardholderNamePrefilled(
!prefilled_name.empty());
// Add cardholder name elements to a single view, then to the final dialog.
std::unique_ptr<views::View> cardholder_name_view =
std::make_unique<views::View>();
cardholder_name_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::kVertical, gfx::Insets(),
provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL)));
cardholder_name_view->AddChildView(cardholder_name_label_row.release());
cardholder_name_view->AddChildView(cardholder_name_textfield_);
view->AddChildView(cardholder_name_view.release());
}
return view;
}
} // namespace autofill