blob: 028929aa1bc24d2b3f23ad76d4af3f838f69d6ea [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 "chrome/browser/ui/views/web_apps/web_app_identity_update_confirmation_view.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.h"
#include "chrome/browser/web_applications/components/web_app_callback_app_identity.h"
#include "chrome/grit/generated_resources.h"
#include "components/constrained_window/constrained_window_views.h"
#include "components/webapps/browser/installable/installable_metrics.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/style/typography.h"
namespace {
const int kArrowIconSize = 32;
bool g_auto_accept_app_identity_update_for_testing = false;
} // namespace
WebAppIdentityUpdateConfirmationView::~WebAppIdentityUpdateConfirmationView() =
default;
WebAppIdentityUpdateConfirmationView::WebAppIdentityUpdateConfirmationView(
const std::string& app_id,
bool title_change,
bool icon_change,
const std::u16string& old_title,
const std::u16string& new_title,
const SkBitmap& old_icon,
const SkBitmap& new_icon,
content::WebContents* web_contents,
web_app::AppIdentityDialogCallback callback) {
app_id_ = app_id;
web_contents_ = web_contents;
DCHECK(!callback.is_null());
callback_ = std::move(callback);
SetButtonLabel(ui::DIALOG_BUTTON_CANCEL,
l10n_util::GetStringUTF16(IDS_WEBAPP_UPDATE_NEGATIVE_BUTTON));
SetModalType(ui::MODAL_TYPE_WINDOW);
DCHECK(title_change || icon_change);
SetTitle(title_change
? (icon_change ? IDS_WEBAPP_UPDATE_DIALOG_TITLE_NAME_AND_ICON
: IDS_WEBAPP_UPDATE_DIALOG_TITLE_NAME)
: IDS_WEBAPP_UPDATE_DIALOG_TITLE_ICON);
SetAcceptCallback(
base::BindOnce(&WebAppIdentityUpdateConfirmationView::OnDialogAccepted,
base::Unretained(this)));
const ChromeLayoutProvider* layout_provider = ChromeLayoutProvider::Get();
set_margins(layout_provider->GetDialogInsetsForContentType(
views::DialogContentType::kControl, views::DialogContentType::kText));
views::GridLayout* layout =
SetLayoutManager(std::make_unique<views::GridLayout>());
// The headline column set is simply a single column that fills up the row.
constexpr int kColumnSetIdHeadline = 0;
views::ColumnSet* column_set_headline =
layout->AddColumnSet(kColumnSetIdHeadline);
column_set_headline->AddColumn(
views::GridLayout::FILL, views::GridLayout::CENTER,
views::GridLayout::kFixedSize,
views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
// The main column set is |padding|col1|padding|arrow|padding|col2|padding|,
// where col1 and col2 contain the 'before' and 'after' values (either text or
// icon) and the first and last columns grow as needed to fill upp the rest.
constexpr int kColumnSetIdMain = 1;
views::ColumnSet* column_set_main = layout->AddColumnSet(kColumnSetIdMain);
// Padding column on the far left side of the dialog. Grows as needed to keep
// the views centered.
column_set_main->AddPaddingColumn(/*resize_percent= */ 100, /* width= */ 0);
// Column showing the 'before' icon/text.
column_set_main->AddColumn(views::GridLayout::CENTER,
views::GridLayout::CENTER,
views::GridLayout::kFixedSize,
views::GridLayout::ColumnSize::kUsePreferred,
/* fixed_width= */ 0, /* min_width= */ 0);
// Padding between the left side and the arrow.
column_set_main->AddPaddingColumn(
views::GridLayout::kFixedSize,
layout_provider->GetDistanceMetric(
views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
// Column showing the arrow to indicate what is before and what is after.
column_set_main->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
views::GridLayout::kFixedSize,
views::GridLayout::ColumnSize::kUsePreferred,
/* fixed_width= */ 0,
/* min_width= */ 0);
// Padding between the arrow and the right side.
column_set_main->AddPaddingColumn(
views::GridLayout::FILL, layout_provider->GetDistanceMetric(
views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
// Column showing the 'after' icon/text.
column_set_main->AddColumn(views::GridLayout::CENTER,
views::GridLayout::CENTER,
views::GridLayout::kFixedSize,
views::GridLayout::ColumnSize::kUsePreferred,
/* fixed_width= */ 0, /* min_width= */ 0);
// Padding column on the far right side of the dialog. Grows as needed to keep
// the views centered.
column_set_main->AddPaddingColumn(/*resize_percent= */ 100, /* width= */ 0);
layout->StartRow(views::GridLayout::kFixedSize, kColumnSetIdHeadline);
auto message_label = std::make_unique<views::Label>(
l10n_util::GetStringUTF16(IDS_WEBAPP_UPDATE_EXPLANATION),
views::style::CONTEXT_LABEL);
message_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
message_label->SetMultiLine(true);
layout->AddView(std::move(message_label));
layout->AddPaddingRow(
views::GridLayout::kFixedSize,
2 * layout_provider->GetDistanceMetric(DISTANCE_CONTROL_LIST_VERTICAL));
layout->StartRow(views::GridLayout::kFixedSize, kColumnSetIdMain);
auto old_icon_image_view = std::make_unique<views::ImageView>();
gfx::Size image_size(web_app::kWebAppIconSmall, web_app::kWebAppIconSmall);
old_icon_image_view->SetImageSize(image_size);
old_icon_image_view->SetImage(gfx::ImageSkia::CreateFrom1xBitmap(old_icon));
layout->AddView(std::move(old_icon_image_view));
auto arrow = std::make_unique<views::ImageView>();
arrow->SetImage(
gfx::CreateVectorIcon(kKeyboardArrowRightIcon, kArrowIconSize,
GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_DefaultIconColor)));
layout->AddView(std::move(arrow));
auto new_icon_image_view = std::make_unique<views::ImageView>();
new_icon_image_view->SetImageSize(image_size);
new_icon_image_view->SetImage(gfx::ImageSkia::CreateFrom1xBitmap(new_icon));
layout->AddView(std::move(new_icon_image_view));
layout->AddPaddingRow(
views::GridLayout::kFixedSize,
layout_provider->GetDistanceMetric(DISTANCE_CONTROL_LIST_VERTICAL));
auto old_title_label =
std::make_unique<views::Label>(old_title, views::style::CONTEXT_LABEL);
auto new_title_label =
std::make_unique<views::Label>(new_title, views::style::CONTEXT_LABEL);
old_title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
new_title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
old_title_label->SetMultiLine(true);
new_title_label->SetMultiLine(true);
layout->StartRow(views::GridLayout::kFixedSize, kColumnSetIdMain);
layout->AddView(std::move(old_title_label));
layout->SkipColumns(1);
layout->AddView(std::move(new_title_label));
chrome::RecordDialogCreation(
chrome::DialogIdentifier::APP_IDENTITY_UPDATE_CONFIRMATION);
}
bool WebAppIdentityUpdateConfirmationView::ShouldShowCloseButton() const {
return false;
}
void WebAppIdentityUpdateConfirmationView::OnDialogAccepted() {
std::move(callback_).Run(web_app::AppIdentityUpdate::kAllowed);
}
bool WebAppIdentityUpdateConfirmationView::Cancel() {
uninstall_dialog_ = std::make_unique<WebAppUninstallDialogViews>(
Profile::FromBrowserContext(web_contents_->GetBrowserContext()),
web_contents_->GetTopLevelNativeWindow());
uninstall_dialog_->show_data_clearing_confirmation(false);
uninstall_dialog_->ConfirmUninstall(
app_id_, webapps::WebappUninstallSource::kAppMenu, base::DoNothing());
return false;
}
BEGIN_METADATA(WebAppIdentityUpdateConfirmationView, views::DialogDelegateView)
END_METADATA
namespace chrome {
void ShowWebAppIdentityUpdateDialog(
const std::string& app_id,
bool title_change,
bool icon_change,
const std::u16string& old_title,
const std::u16string& new_title,
const SkBitmap& old_icon,
const SkBitmap& new_icon,
content::WebContents* web_contents,
web_app::AppIdentityDialogCallback callback) {
auto* dialog = new WebAppIdentityUpdateConfirmationView(
app_id, title_change, icon_change, old_title, new_title, old_icon,
new_icon, web_contents, std::move(callback));
views::Widget* dialog_widget =
constrained_window::CreateBrowserModalDialogViews(
dialog, web_contents->GetTopLevelNativeWindow());
dialog_widget->Show();
if (g_auto_accept_app_identity_update_for_testing) {
dialog->AcceptDialog();
}
}
void SetAutoAcceptAppIdentityUpdateForTesting(bool auto_accept) {
g_auto_accept_app_identity_update_for_testing = auto_accept;
}
} // namespace chrome