blob: 47d481e9dcc0b4e6280c91806c0d6c51625bd349 [file] [log] [blame]
// Copyright 2021 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 "ash/in_session_auth/authentication_dialog.h"
#include <memory>
#include "ash/public/cpp/shelf_config.h"
#include "ash/strings/grit/ash_strings.h"
#include "base/bind.h"
#include "base/time/time.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/ui_base_types.h"
#include "ui/display/screen.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/layout/flex_layout.h"
#include "ui/views/layout/layout_provider.h"
#include "ui/views/layout/layout_types.h"
#include "ui/views/view_class_properties.h"
#include "ui/views/widget/widget.h"
namespace ash {
namespace {
void AddMargins(views::View* view) {
const auto* layout_provider = views::LayoutProvider::Get();
const int horizontal_spacing = layout_provider->GetDistanceMetric(
views::DISTANCE_RELATED_CONTROL_HORIZONTAL);
const int vertical_spacing = layout_provider->GetDistanceMetric(
views::DISTANCE_RELATED_CONTROL_VERTICAL);
view->SetProperty(views::kMarginsKey,
gfx::Insets::VH(vertical_spacing, horizontal_spacing));
}
void ConfigurePasswordField(views::Textfield* password_field) {
const auto password_field_name =
l10n_util::GetStringUTF16(IDS_ASH_LOGIN_POD_PASSWORD_PLACEHOLDER);
password_field->SetAccessibleName(password_field_name);
password_field->SetReadOnly(false);
password_field->SetTextInputType(ui::TextInputType::TEXT_INPUT_TYPE_PASSWORD);
password_field->SetPlaceholderText(password_field_name);
AddMargins(password_field);
}
void ConfigureInvalidPasswordLabel(views::Label* invalid_password_label) {
invalid_password_label->SetProperty(views::kCrossAxisAlignmentKey,
views::LayoutAlignment::kStart);
invalid_password_label->SetEnabledColor(SK_ColorRED);
AddMargins(invalid_password_label);
}
void CenterWidgetOnPrimaryDisplay(views::Widget* widget) {
auto bounds = display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
bounds.ClampToCenteredSize(widget->GetContentsView()->GetPreferredSize());
widget->SetBounds(bounds);
}
} // namespace
// static
AuthenticationDialog* AuthenticationDialog::Show(
OnSubmitCallback submit_callback) {
auto* authentication_dialog =
new AuthenticationDialog(std::move(submit_callback));
auto* widget = DialogDelegateView::CreateDialogWidget(authentication_dialog,
/*context=*/nullptr,
/*parent=*/nullptr);
CenterWidgetOnPrimaryDisplay(widget);
widget->Show();
authentication_dialog->Init();
return authentication_dialog;
}
AuthenticationDialog::~AuthenticationDialog() = default;
void AuthenticationDialog::Init() {
ConfigureOkButton();
password_field_->RequestFocus();
}
void AuthenticationDialog::NotifyResult(Result result,
const std::u16string& token,
base::TimeDelta timeout) {
std::move(on_submit_).Run(result, token, timeout);
}
void AuthenticationDialog::CancelAuthAttempt() {
NotifyResult(Result::kAborted, u"", base::Seconds(0));
}
void AuthenticationDialog::OnSubmit() {
// TODO(crbug.com/1271551): Call appropriate backends to get token
// and notify interested parties with |AuthenticationDialog::NotifyResult|
// For now, we always assume the given password is invalid
password_field_->SetInvalid(true);
password_field_->SelectAll(false);
invalid_password_label_->SetText(
l10n_util::GetStringUTF16(IDS_ASH_LOGIN_ERROR_AUTHENTICATING));
}
void AuthenticationDialog::ConfigureChildViews() {
ConfigurePasswordField(password_field_);
ConfigureInvalidPasswordLabel(invalid_password_label_);
}
void AuthenticationDialog::ConfigureOkButton() {
views::LabelButton* ok_button = GetOkButton();
ok_button->SetText(
l10n_util::GetStringUTF16(IDS_ASH_LOGIN_SUBMIT_BUTTON_ACCESSIBLE_NAME));
ok_button->SetCallback(base::BindRepeating(&AuthenticationDialog::OnSubmit,
base::Unretained(this)));
}
AuthenticationDialog::AuthenticationDialog(OnSubmitCallback submit_callback)
: password_field_(AddChildView(std::make_unique<views::Textfield>())),
invalid_password_label_(AddChildView(std::make_unique<views::Label>())),
on_submit_(std::move(submit_callback)) {
// Dialog setup
set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(
views::DistanceMetric::DISTANCE_BUBBLE_PREFERRED_WIDTH));
SetTitle(l10n_util::GetStringUTF16(IDS_ASH_IN_SESSION_AUTH_TITLE));
SetModalType(ui::MODAL_TYPE_SYSTEM);
// Callback setup
SetCancelCallback(base::BindOnce(&AuthenticationDialog::CancelAuthAttempt,
base::Unretained(this)));
SetCloseCallback(base::BindOnce(&AuthenticationDialog::CancelAuthAttempt,
base::Unretained(this)));
SetLayoutManager(std::make_unique<views::FlexLayout>())
->SetOrientation(views::LayoutOrientation::kVertical)
.SetCollapseMargins(true);
ConfigureChildViews();
}
} // namespace ash