blob: 0027787de98ee8253a19b2a23a910dab8efb0fb4 [file] [log] [blame]
// Copyright 2017 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/pwa_confirmation_view.h"
#include <memory>
#include <utility>
#include "base/callback_helpers.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/views/extensions/web_app_info_image_source.h"
#include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
#include "chrome/browser/ui/views/harmony/chrome_typography.h"
#include "chrome/grit/generated_resources.h"
#include "components/constrained_window/constrained_window_views.h"
#include "components/strings/grit/components_strings.h"
#include "components/url_formatter/elide_url.h"
#include "extensions/common/constants.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/text_elider.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/style/typography.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/dialog_client_view.h"
#include "url/origin.h"
constexpr int kPWAConfirmationViewIconSize = 48;
PWAConfirmationView::PWAConfirmationView(
const WebApplicationInfo& web_app_info,
chrome::AppInstallationAcceptanceCallback callback)
: web_app_info_(web_app_info), callback_(std::move(callback)) {
base::TrimWhitespace(web_app_info_.title, base::TRIM_ALL,
&web_app_info_.title);
// PWAs should always be configured to open in a window.
DCHECK(web_app_info_.open_as_window);
InitializeView();
chrome::RecordDialogCreation(chrome::DialogIdentifier::PWA_CONFIRMATION);
}
PWAConfirmationView::~PWAConfirmationView() {}
gfx::Size PWAConfirmationView::CalculatePreferredSize() const {
int bubble_width = ChromeLayoutProvider::Get()->GetDistanceMetric(
DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH);
gfx::Size size = views::DialogDelegateView::CalculatePreferredSize();
size.SetToMin(gfx::Size(bubble_width - margins().width(), size.height()));
return size;
}
ui::ModalType PWAConfirmationView::GetModalType() const {
return ui::MODAL_TYPE_CHILD;
}
base::string16 PWAConfirmationView::GetWindowTitle() const {
return l10n_util::GetStringUTF16(
IDS_INSTALL_TO_OS_LAUNCH_SURFACE_BUBBLE_TITLE);
}
bool PWAConfirmationView::ShouldShowCloseButton() const {
return false;
}
void PWAConfirmationView::WindowClosing() {
if (callback_)
std::move(callback_).Run(false, web_app_info_);
}
bool PWAConfirmationView::Accept() {
base::ResetAndReturn(&callback_).Run(true, web_app_info_);
return true;
}
base::string16 PWAConfirmationView::GetDialogButtonLabel(
ui::DialogButton button) const {
return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK ? IDS_ADD
: IDS_CANCEL);
}
namespace {
// Returns an ImageView containing the app icon.
std::unique_ptr<views::ImageView> CreateIconView(
const std::vector<WebApplicationInfo::IconInfo>& icons) {
gfx::ImageSkia image(
std::make_unique<WebAppInfoImageSource>(kPWAConfirmationViewIconSize,
icons),
gfx::Size(kPWAConfirmationViewIconSize, kPWAConfirmationViewIconSize));
auto icon_image_view = std::make_unique<views::ImageView>();
icon_image_view->SetImage(image);
return icon_image_view;
}
// Returns a label containing the app name.
std::unique_ptr<views::Label> CreateNameLabel(const base::string16& name) {
auto name_label = std::make_unique<views::Label>(
name, CONTEXT_BODY_TEXT_LARGE, views::style::TextStyle::STYLE_PRIMARY);
name_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
name_label->SetElideBehavior(gfx::ELIDE_TAIL);
return name_label;
}
std::unique_ptr<views::Label> CreateOriginLabel(const url::Origin& origin) {
auto origin_label = std::make_unique<views::Label>(
FormatOriginForSecurityDisplay(
origin, url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS),
CONTEXT_BODY_TEXT_SMALL, STYLE_SECONDARY);
origin_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
// Elide from head to prevent origin spoofing.
origin_label->SetElideBehavior(gfx::ELIDE_HEAD);
// Multiline breaks elision, so explicitly disable multiline.
origin_label->SetMultiLine(false);
return origin_label;
}
} // namespace
void PWAConfirmationView::InitializeView() {
const ChromeLayoutProvider* layout_provider = ChromeLayoutProvider::Get();
// Use CONTROL insets, because the icon is non-text (see documentation for
// DialogContentType).
gfx::Insets margin_insets = layout_provider->GetDialogInsetsForContentType(
views::CONTROL, views::CONTROL);
set_margins(margin_insets);
int icon_label_spacing = layout_provider->GetDistanceMetric(
views::DISTANCE_RELATED_CONTROL_HORIZONTAL);
SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
gfx::Insets(), icon_label_spacing));
AddChildView(CreateIconView(web_app_info_.icons).release());
views::View* labels = new views::View();
AddChildView(labels);
labels->SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical));
labels->AddChildView(CreateNameLabel(web_app_info_.title).release());
labels->AddChildView(
CreateOriginLabel(url::Origin::Create(web_app_info_.app_url)).release());
}
namespace chrome {
void ShowPWAInstallDialog(content::WebContents* web_contents,
const WebApplicationInfo& web_app_info,
AppInstallationAcceptanceCallback callback) {
constrained_window::ShowWebModalDialogViews(
new PWAConfirmationView(web_app_info, std::move(callback)), web_contents);
}
} // namespace chrome