1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/views/extensions/settings_overridden_dialog_view.h"
6
7 #include "base/bind.h"
8 #include "chrome/browser/ui/browser.h"
9 #include "chrome/browser/ui/browser_window.h"
10 #include "chrome/browser/ui/views/chrome_layout_provider.h"
11 #include "chrome/browser/ui/views/chrome_typography.h"
12 #include "chrome/grit/generated_resources.h"
13 #include "components/constrained_window/constrained_window_views.h"
14 #include "ui/base/l10n/l10n_util.h"
15 #include "ui/gfx/color_palette.h"
16 #include "ui/gfx/paint_vector_icon.h"
17 #include "ui/views/controls/label.h"
18 #include "ui/views/layout/fill_layout.h"
19
SettingsOverriddenDialogView(std::unique_ptr<SettingsOverriddenDialogController> controller)20 SettingsOverriddenDialogView::SettingsOverriddenDialogView(
21 std::unique_ptr<SettingsOverriddenDialogController> controller)
22 : controller_(std::move(controller)) {
23 SetButtonLabel(ui::DIALOG_BUTTON_OK,
24 l10n_util::GetStringUTF16(
25 IDS_EXTENSION_SETTINGS_OVERRIDDEN_DIALOG_CHANGE_IT_BACK));
26 SetButtonLabel(ui::DIALOG_BUTTON_CANCEL,
27 l10n_util::GetStringUTF16(
28 IDS_EXTENSION_SETTINGS_OVERRIDDEN_DIALOG_KEEP_IT));
29 SetLayoutManager(std::make_unique<views::FillLayout>());
30 ChromeLayoutProvider* const layout_provider = ChromeLayoutProvider::Get();
31 set_margins(
32 layout_provider->GetDialogInsetsForContentType(views::TEXT, views::TEXT));
33
34 using DialogResult = SettingsOverriddenDialogController::DialogResult;
35 auto make_result_callback = [this](DialogResult result) {
36 // NOTE: The following Bind's are safe because the callback is
37 // owned by this object (indirectly, as a DialogDelegate).
38 return base::BindOnce(
39 &SettingsOverriddenDialogView::NotifyControllerOfResult,
40 base::Unretained(this), result);
41 };
42 SetAcceptCallback(make_result_callback(DialogResult::kChangeSettingsBack));
43 SetCancelCallback(make_result_callback(DialogResult::kKeepNewSettings));
44 SetCloseCallback(make_result_callback(DialogResult::kDialogDismissed));
45
46 // Modals shouldn't show a close button according to the latest style
47 // guidelines. Note the dialog can still be dismissed by user action via the
48 // escape key (in addition to closing automatically if the parent widget
49 // is destroyed).
50 SetShowCloseButton(false);
51
52 SettingsOverriddenDialogController::ShowParams show_params =
53 controller_->GetShowParams();
54
55 SetTitle(show_params.dialog_title);
56
57 if (show_params.icon) {
58 SetShowIcon(true);
59 // Note: Any icons added *should* fully specify their own color, so this
60 // will be a no-op. But, the call requires a color, and this enables testing
61 // with other icons and a reasonable fallback.
62 constexpr SkColor kPlaceholderColor = gfx::kGoogleGrey500;
63 SetIcon(gfx::CreateVectorIcon(*show_params.icon,
64 layout_provider->GetDistanceMetric(
65 DISTANCE_BUBBLE_HEADER_VECTOR_ICON_SIZE),
66 kPlaceholderColor));
67 }
68
69 auto message_label = std::make_unique<views::Label>(
70 show_params.message, views::style::CONTEXT_DIALOG_BODY_TEXT,
71 views::style::STYLE_SECONDARY);
72 message_label->SetMultiLine(true);
73 message_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
74 AddChildView(std::move(message_label));
75 }
76
~SettingsOverriddenDialogView()77 SettingsOverriddenDialogView::~SettingsOverriddenDialogView() {
78 if (!result_) {
79 // The dialog may close without firing any of the [accept | cancel | close]
80 // callbacks if e.g. the parent window closes. In this case, notify the
81 // controller that the dialog closed without user action.
82 controller_->HandleDialogResult(
83 SettingsOverriddenDialogController::DialogResult::
84 kDialogClosedWithoutUserAction);
85 }
86 }
87
Show(gfx::NativeWindow parent)88 void SettingsOverriddenDialogView::Show(gfx::NativeWindow parent) {
89 constrained_window::CreateBrowserModalDialogViews(this, parent)->Show();
90 controller_->OnDialogShown();
91 }
92
GetModalType() const93 ui::ModalType SettingsOverriddenDialogView::GetModalType() const {
94 return ui::MODAL_TYPE_WINDOW;
95 }
96
CalculatePreferredSize() const97 gfx::Size SettingsOverriddenDialogView::CalculatePreferredSize() const {
98 const int width = ChromeLayoutProvider::Get()->GetDistanceMetric(
99 views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH) -
100 margins().width();
101 return gfx::Size(width, GetHeightForWidth(width));
102 }
103
NotifyControllerOfResult(SettingsOverriddenDialogController::DialogResult result)104 void SettingsOverriddenDialogView::NotifyControllerOfResult(
105 SettingsOverriddenDialogController::DialogResult result) {
106 DCHECK(!result_)
107 << "Trying to re-notify controller of result. Previous result: "
108 << static_cast<int>(*result_)
109 << ", new result: " << static_cast<int>(result);
110 result_ = result;
111 controller_->HandleDialogResult(result);
112 }
113
114 namespace chrome {
115
ShowExtensionSettingsOverriddenDialog(std::unique_ptr<SettingsOverriddenDialogController> controller,Browser * browser)116 void ShowExtensionSettingsOverriddenDialog(
117 std::unique_ptr<SettingsOverriddenDialogController> controller,
118 Browser* browser) {
119 // Note: ownership is taken by the view hierarchy.
120 auto* dialog_view = new SettingsOverriddenDialogView(std::move(controller));
121 dialog_view->Show(browser->window()->GetNativeWindow());
122 }
123
124 } // namespace chrome
125