blob: a7e7a8a67fbe8742197fbce112f520a5f816fe41 [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/policy/enterprise_startup_dialog_view.h"
#include <memory>
#include <utility>
#include "base/i18n/message_formatter.h"
#include "base/strings/string16.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/views/chrome_layout_provider.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/theme_resources.h"
#include "components/constrained_window/constrained_window_views.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/throbber.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/window/dialog_client_view.h"
#if defined(OS_MACOSX)
#include "base/message_loop/message_loop_current.h"
#include "chrome/browser/ui/views/policy/enterprise_startup_dialog_mac_util.h"
#endif
namespace policy {
namespace {
constexpr int kDialogContentHeight = 190; // The height of dialog content area.
constexpr int kDialogContentWidth = 670; // The width of dialog content area.
constexpr int kIconSize = 24; // The size of throbber and error icon.
constexpr int kLineHeight = 22; // The height of text line.
constexpr int kFontSizeDelta = 3; // The font size of text.
#if defined(GOOGLE_CHROME_BUILD)
constexpr int kLogoHeight = 20; // The height of Chrome enterprise logo.
#endif
gfx::Insets GetDialogInsets() {
return ChromeLayoutProvider::Get()->GetDialogInsetsForContentType(
views::CONTROL, views::TEXT);
}
views::Label* CreateText(const base::string16& message) {
views::Label* text = new views::Label(message);
text->SetFontList(gfx::FontList().Derive(kFontSizeDelta, gfx::Font::NORMAL,
gfx::Font::Weight::MEDIUM));
text->SetEnabledColor(gfx::kGoogleGrey700);
text->SetLineHeight(kLineHeight);
return text;
}
} // namespace
EnterpriseStartupDialogView::EnterpriseStartupDialogView(
EnterpriseStartupDialog::DialogResultCallback callback)
: callback_(std::move(callback)),
can_show_browser_window_(false),
weak_factory_(this) {
SetBorder(views::CreateEmptyBorder(GetDialogInsets()));
CreateDialogWidget(this, nullptr, nullptr)->Show();
#if defined(OS_MACOSX)
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&EnterpriseStartupDialogView::StartModalDialog,
weak_factory_.GetWeakPtr()));
#endif
}
EnterpriseStartupDialogView::~EnterpriseStartupDialogView() {}
void EnterpriseStartupDialogView::DisplayLaunchingInformationWithThrobber(
const base::string16& information) {
ResetDialog(false);
views::Label* text = CreateText(information);
views::Throbber* throbber = new views::Throbber();
gfx::Size throbber_size = gfx::Size(kIconSize, kIconSize);
throbber->SetPreferredSize(throbber_size);
throbber->Start();
SetupLayout(throbber, text);
}
void EnterpriseStartupDialogView::DisplayErrorMessage(
const base::string16& error_message,
const base::Optional<base::string16>& accept_button) {
ResetDialog(accept_button.has_value());
views::Label* text = CreateText(error_message);
views::ImageView* error_icon = new views::ImageView();
error_icon->SetImage(gfx::CreateVectorIcon(kBrowserToolsErrorIcon, kIconSize,
gfx::kGoogleRed700));
if (accept_button)
GetDialogClientView()->ok_button()->SetText(*accept_button);
SetupLayout(error_icon, text);
}
void EnterpriseStartupDialogView::CloseDialog() {
can_show_browser_window_ = true;
GetWidget()->Close();
}
void EnterpriseStartupDialogView::AddWidgetObserver(
views::WidgetObserver* observer) {
GetWidget()->AddObserver(observer);
}
void EnterpriseStartupDialogView::RemoveWidgetObserver(
views::WidgetObserver* observer) {
GetWidget()->RemoveObserver(observer);
}
void EnterpriseStartupDialogView::StartModalDialog() {
#if defined(OS_MACOSX)
base::MessageLoopCurrent::ScopedNestableTaskAllower allow_nested;
StartModal(GetWidget()->GetNativeWindow());
#endif
}
void EnterpriseStartupDialogView::RunDialogCallback(bool was_accepted) {
#if defined(OS_MACOSX)
// On mac, we need to stop the modal message loop before returning the result
// to the caller who controls its own run loop.
StopModal();
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback_), was_accepted,
can_show_browser_window_));
#else
std::move(callback_).Run(was_accepted, can_show_browser_window_);
#endif
}
bool EnterpriseStartupDialogView::Accept() {
RunDialogCallback(true);
return true;
}
bool EnterpriseStartupDialogView::Cancel() {
RunDialogCallback(false);
return true;
}
bool EnterpriseStartupDialogView::Close() {
return Cancel();
}
bool EnterpriseStartupDialogView::ShouldShowWindowTitle() const {
return false;
}
ui::ModalType EnterpriseStartupDialogView::GetModalType() const {
return ui::MODAL_TYPE_NONE;
}
views::View* EnterpriseStartupDialogView::CreateExtraView() {
#if defined(GOOGLE_CHROME_BUILD)
// Show Google Chrome Enterprise logo only for official build.
views::ImageView* logo_image = new views::ImageView();
logo_image->SetImage(ui::ResourceBundle::GetSharedInstance()
.GetImageNamed(IDR_PRODUCT_LOGO_ENTERPRISE)
.AsImageSkia());
logo_image->set_tooltip_text(
l10n_util::GetStringUTF16(IDS_PRODUCT_LOGO_ENTERPRISE_ALT_TEXT));
gfx::Rect logo_bounds = logo_image->GetImageBounds();
logo_image->SetImageSize(gfx::Size(
logo_bounds.width() * kLogoHeight / logo_bounds.height(), kLogoHeight));
logo_image->SetVerticalAlignment(views::ImageView::CENTER);
return logo_image;
#else
return nullptr;
#endif
}
int EnterpriseStartupDialogView::GetDialogButtons() const {
return ui::DIALOG_BUTTON_OK;
}
gfx::Size EnterpriseStartupDialogView::CalculatePreferredSize() const {
return gfx::Size(kDialogContentWidth, kDialogContentHeight);
}
void EnterpriseStartupDialogView::ResetDialog(bool show_accept_button) {
DCHECK(GetDialogClientView()->ok_button());
GetDialogClientView()->ok_button()->SetVisible(show_accept_button);
RemoveAllChildViews(true);
}
void EnterpriseStartupDialogView::SetupLayout(views::View* icon,
views::View* text) {
// Padding between icon and text
int text_padding = ChromeLayoutProvider::Get()->GetDistanceMetric(
views::DISTANCE_TEXTFIELD_HORIZONTAL_TEXT_PADDING);
views::GridLayout* layout =
SetLayoutManager(std::make_unique<views::GridLayout>(this));
auto* columnset = layout->AddColumnSet(0);
// Horizontally centre the content.
columnset->AddPaddingColumn(1.0, 0);
columnset->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
views::GridLayout::kFixedSize,
views::GridLayout::USE_PREF, 0, 0);
columnset->AddPaddingColumn(views::GridLayout::kFixedSize, text_padding);
columnset->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
views::GridLayout::kFixedSize,
views::GridLayout::USE_PREF, 0, 0);
columnset->AddPaddingColumn(1.0, 0);
layout->AddPaddingRow(1.0, 0);
layout->StartRow(views::GridLayout::kFixedSize, 0);
layout->AddView(icon);
layout->AddView(text);
layout->AddPaddingRow(1.0, 0);
GetDialogClientView()->Layout();
GetDialogClientView()->SchedulePaint();
}
/*
* EnterpriseStartupDialogImpl
*/
EnterpriseStartupDialogImpl::EnterpriseStartupDialogImpl(
DialogResultCallback callback) {
dialog_view_ = new EnterpriseStartupDialogView(std::move(callback));
dialog_view_->AddWidgetObserver(this);
}
EnterpriseStartupDialogImpl::~EnterpriseStartupDialogImpl() {
if (dialog_view_) {
dialog_view_->RemoveWidgetObserver(this);
dialog_view_->CloseDialog();
}
}
void EnterpriseStartupDialogImpl::DisplayLaunchingInformationWithThrobber(
const base::string16& information) {
if (dialog_view_)
dialog_view_->DisplayLaunchingInformationWithThrobber(information);
}
void EnterpriseStartupDialogImpl::DisplayErrorMessage(
const base::string16& error_message,
const base::Optional<base::string16>& accept_button) {
if (dialog_view_)
dialog_view_->DisplayErrorMessage(error_message, accept_button);
}
bool EnterpriseStartupDialogImpl::IsShowing() {
return dialog_view_;
}
// views::WidgetObserver:
void EnterpriseStartupDialogImpl::OnWidgetClosing(views::Widget* widget) {
dialog_view_->RemoveWidgetObserver(this);
dialog_view_ = nullptr;
}
/*
* EnterpriseStartupDialog
*/
// static
std::unique_ptr<EnterpriseStartupDialog>
EnterpriseStartupDialog::CreateAndShowDialog(DialogResultCallback callback) {
return std::make_unique<EnterpriseStartupDialogImpl>(std::move(callback));
}
} // namespace policy