blob: 43e2e561154d31a555dc107f7dfa77f16ea8aa13 [file] [log] [blame]
// Copyright 2020 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/extensions/extension_install_blocked_dialog_view.h"
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/i18n/message_formatter.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/chrome_typography.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/grit/generated_resources.h"
#include "components/constrained_window/constrained_window_views.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/common/constants.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/views/border.h"
#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/scroll_view.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/widget/widget.h"
namespace chrome {
void ShowExtensionInstallBlockedDialog(
const std::string& extension_id,
const std::string& extension_name,
const std::u16string& custom_error_message,
const gfx::ImageSkia& icon,
content::WebContents* web_contents,
base::OnceClosure done_callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
auto dialog = std::make_unique<ExtensionInstallBlockedDialogView>(
extension_id, extension_name, custom_error_message, icon,
std::move(done_callback));
constrained_window::ShowWebModalDialogViews(dialog.release(), web_contents)
->Show();
}
} // namespace chrome
ExtensionInstallBlockedDialogView::ExtensionInstallBlockedDialogView(
const std::string& extension_id,
const std::string& extension_name,
const std::u16string& custom_error_message,
const gfx::ImageSkia& icon,
base::OnceClosure done_callback)
: done_callback_(std::move(done_callback)) {
SetButtons(ui::DIALOG_BUTTON_CANCEL);
SetDefaultButton(ui::DIALOG_BUTTON_CANCEL);
SetButtonLabel(ui::DIALOG_BUTTON_CANCEL,
l10n_util::GetStringUTF16(IDS_CLOSE));
SetShowIcon(true);
SetIcon(gfx::ImageSkiaOperations::CreateResizedImage(
icon, skia::ImageOperations::ResizeMethod::RESIZE_BEST,
gfx::Size(extension_misc::EXTENSION_ICON_SMALL,
extension_misc::EXTENSION_ICON_SMALL)));
SetTitle(l10n_util::GetStringFUTF16(
IDS_EXTENSION_BLOCKED_BY_POLICY_PROMPT_TITLE,
base::UTF8ToUTF16(extension_name), base::UTF8ToUTF16(extension_id)));
// Make sure user know the installation is blocked before taking further
// action.
SetModalType(ui::MODAL_TYPE_CHILD);
set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(
views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH));
set_draggable(true);
set_close_on_deactivate(false);
SetLayoutManager(std::make_unique<views::FillLayout>());
if (!custom_error_message.empty())
AddCustomMessageContents(custom_error_message);
}
ExtensionInstallBlockedDialogView::~ExtensionInstallBlockedDialogView() {
if (done_callback_)
std::move(done_callback_).Run();
}
void ExtensionInstallBlockedDialogView::AddCustomMessageContents(
const std::u16string& custom_error_message) {
DCHECK(!custom_error_message.empty());
const ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
auto extension_info_container = std::make_unique<views::View>();
const gfx::Insets content_insets = provider->GetDialogInsetsForContentType(
views::DialogContentType::kText, views::DialogContentType::kText);
extension_info_container->SetBorder(views::CreateEmptyBorder(
gfx::Insets::TLBR(0, content_insets.left(), 0, content_insets.right())));
extension_info_container->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical, gfx::Insets(),
provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL)));
const int content_width = GetPreferredSize().width() -
extension_info_container->GetInsets().width();
set_margins(
gfx::Insets::TLBR(content_insets.top(), 0, content_insets.bottom(), 0));
auto* header_label =
extension_info_container->AddChildView(std::make_unique<views::Label>(
custom_error_message, views::style::CONTEXT_DIALOG_BODY_TEXT));
header_label->SetMultiLine(true);
header_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
header_label->SizeToFit(content_width);
auto* scroll_view = AddChildView(std::make_unique<views::ScrollView>());
scroll_view->SetHorizontalScrollBarMode(
views::ScrollView::ScrollBarMode::kDisabled);
scroll_view->SetContents(std::move(extension_info_container));
scroll_view->ClipHeightTo(
0, provider->GetDistanceMetric(
views::DISTANCE_DIALOG_SCROLLABLE_AREA_MAX_HEIGHT));
}
BEGIN_METADATA(ExtensionInstallBlockedDialogView,
views::BubbleDialogDelegateView)
END_METADATA