[Extensions] Make extension message bubble factory platform-abstract
[chromium-blink-merge.git] / chrome / browser / ui / views / simple_message_box_views.cc
blobe89c673e525f2a37b22acac4b3948fa2b94514c5
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/ui/simple_message_box.h"
7 #include "base/basictypes.h"
8 #include "base/compiler_specific.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "chrome/grit/generated_resources.h"
12 #include "components/constrained_window/constrained_window_views.h"
13 #include "ui/base/l10n/l10n_util.h"
14 #include "ui/base/resource/resource_bundle.h"
15 #include "ui/gfx/native_widget_types.h"
16 #include "ui/views/controls/message_box_view.h"
17 #include "ui/views/widget/widget.h"
18 #include "ui/views/window/dialog_delegate.h"
20 #if defined(OS_WIN)
21 #include "ui/base/win/message_box_win.h"
22 #include "ui/views/win/hwnd_util.h"
23 #endif
25 namespace chrome {
27 namespace {
29 class SimpleMessageBoxViews : public views::DialogDelegate {
30 public:
31 SimpleMessageBoxViews(const base::string16& title,
32 const base::string16& message,
33 MessageBoxType type,
34 const base::string16& yes_text,
35 const base::string16& no_text,
36 bool is_system_modal);
37 ~SimpleMessageBoxViews() override;
39 MessageBoxResult RunDialogAndGetResult();
41 // Overridden from views::DialogDelegate:
42 int GetDialogButtons() const override;
43 base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
44 bool Cancel() override;
45 bool Accept() override;
47 // Overridden from views::WidgetDelegate:
48 base::string16 GetWindowTitle() const override;
49 void DeleteDelegate() override;
50 ui::ModalType GetModalType() const override;
51 views::View* GetContentsView() override;
52 views::Widget* GetWidget() override;
53 const views::Widget* GetWidget() const override;
55 private:
57 // This terminates the nested message-loop.
58 void Done();
60 const base::string16 window_title_;
61 const MessageBoxType type_;
62 base::string16 yes_text_;
63 base::string16 no_text_;
64 MessageBoxResult* result_;
65 bool is_system_modal_;
66 views::MessageBoxView* message_box_view_;
67 base::Closure quit_runloop_;
69 DISALLOW_COPY_AND_ASSIGN(SimpleMessageBoxViews);
72 ////////////////////////////////////////////////////////////////////////////////
73 // SimpleMessageBoxViews, public:
75 SimpleMessageBoxViews::SimpleMessageBoxViews(const base::string16& title,
76 const base::string16& message,
77 MessageBoxType type,
78 const base::string16& yes_text,
79 const base::string16& no_text,
80 bool is_system_modal)
81 : window_title_(title),
82 type_(type),
83 yes_text_(yes_text),
84 no_text_(no_text),
85 result_(NULL),
86 is_system_modal_(is_system_modal),
87 message_box_view_(new views::MessageBoxView(
88 views::MessageBoxView::InitParams(message))) {
89 if (yes_text_.empty()) {
90 if (type_ == MESSAGE_BOX_TYPE_QUESTION)
91 yes_text_ =
92 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL);
93 else if (type_ == MESSAGE_BOX_TYPE_OK_CANCEL)
94 yes_text_ = l10n_util::GetStringUTF16(IDS_OK);
95 else
96 yes_text_ = l10n_util::GetStringUTF16(IDS_OK);
99 if (no_text_.empty()) {
100 if (type_ == MESSAGE_BOX_TYPE_QUESTION)
101 no_text_ =
102 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL);
103 else if (type_ == MESSAGE_BOX_TYPE_OK_CANCEL)
104 no_text_ = l10n_util::GetStringUTF16(IDS_CANCEL);
108 SimpleMessageBoxViews::~SimpleMessageBoxViews() {
111 MessageBoxResult SimpleMessageBoxViews::RunDialogAndGetResult() {
112 MessageBoxResult result = MESSAGE_BOX_RESULT_NO;
113 result_ = &result;
114 // TODO(pkotwicz): Exit message loop when the dialog is closed by some other
115 // means than |Cancel| or |Accept|. crbug.com/404385
116 base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
117 base::MessageLoopForUI::ScopedNestableTaskAllower allow_nested(loop);
118 base::RunLoop run_loop;
119 quit_runloop_ = run_loop.QuitClosure();
120 run_loop.Run();
121 return result;
124 int SimpleMessageBoxViews::GetDialogButtons() const {
125 if (type_ == MESSAGE_BOX_TYPE_QUESTION ||
126 type_ == MESSAGE_BOX_TYPE_OK_CANCEL) {
127 return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL;
130 return ui::DIALOG_BUTTON_OK;
133 base::string16 SimpleMessageBoxViews::GetDialogButtonLabel(
134 ui::DialogButton button) const {
135 if (button == ui::DIALOG_BUTTON_CANCEL)
136 return no_text_;
137 return yes_text_;
140 bool SimpleMessageBoxViews::Cancel() {
141 *result_ = MESSAGE_BOX_RESULT_NO;
142 Done();
143 return true;
146 bool SimpleMessageBoxViews::Accept() {
147 *result_ = MESSAGE_BOX_RESULT_YES;
148 Done();
149 return true;
152 base::string16 SimpleMessageBoxViews::GetWindowTitle() const {
153 return window_title_;
156 void SimpleMessageBoxViews::DeleteDelegate() {
157 delete this;
160 ui::ModalType SimpleMessageBoxViews::GetModalType() const {
161 return is_system_modal_ ? ui::MODAL_TYPE_SYSTEM : ui::MODAL_TYPE_WINDOW;
164 views::View* SimpleMessageBoxViews::GetContentsView() {
165 return message_box_view_;
168 views::Widget* SimpleMessageBoxViews::GetWidget() {
169 return message_box_view_->GetWidget();
172 const views::Widget* SimpleMessageBoxViews::GetWidget() const {
173 return message_box_view_->GetWidget();
176 ////////////////////////////////////////////////////////////////////////////////
177 // SimpleMessageBoxViews, private:
179 void SimpleMessageBoxViews::Done() {
180 CHECK(!quit_runloop_.is_null());
181 quit_runloop_.Run();
184 #if defined(OS_WIN)
185 UINT GetMessageBoxFlagsFromType(MessageBoxType type) {
186 UINT flags = MB_SETFOREGROUND;
187 switch (type) {
188 case MESSAGE_BOX_TYPE_INFORMATION:
189 return flags | MB_OK | MB_ICONINFORMATION;
190 case MESSAGE_BOX_TYPE_WARNING:
191 return flags | MB_OK | MB_ICONWARNING;
192 case MESSAGE_BOX_TYPE_QUESTION:
193 return flags | MB_YESNO | MB_ICONQUESTION;
194 case MESSAGE_BOX_TYPE_OK_CANCEL:
195 return flags | MB_OKCANCEL | MB_ICONWARNING;
197 NOTREACHED();
198 return flags | MB_OK | MB_ICONWARNING;
200 #endif
202 MessageBoxResult ShowMessageBoxImpl(gfx::NativeWindow parent,
203 const base::string16& title,
204 const base::string16& message,
205 MessageBoxType type,
206 const base::string16& yes_text,
207 const base::string16& no_text) {
208 // Views dialogs cannot be shown outside the UI thread message loop or if the
209 // ResourceBundle is not initialized yet.
210 // Fallback to logging with a default response or a Windows MessageBox.
211 #if defined(OS_WIN)
212 if (!base::MessageLoopForUI::IsCurrent() ||
213 !base::MessageLoopForUI::current()->is_running() ||
214 !ResourceBundle::HasSharedInstance()) {
215 int result = ui::MessageBox(views::HWNDForNativeWindow(parent), message,
216 title, GetMessageBoxFlagsFromType(type));
217 return (result == IDYES || result == IDOK) ?
218 MESSAGE_BOX_RESULT_YES : MESSAGE_BOX_RESULT_NO;
220 #else
221 if (!base::MessageLoopForUI::IsCurrent() ||
222 !ResourceBundle::HasSharedInstance()) {
223 LOG(ERROR) << "Unable to show a dialog outside the UI thread message loop: "
224 << title << " - " << message;
225 return MESSAGE_BOX_RESULT_NO;
227 #endif
229 SimpleMessageBoxViews* dialog =
230 new SimpleMessageBoxViews(title,
231 message,
232 type,
233 yes_text,
234 no_text,
235 parent == NULL // is_system_modal
237 constrained_window::CreateBrowserModalDialogViews(dialog, parent)->Show();
239 // NOTE: |dialog| may have been deleted by the time |RunDialogAndGetResult()|
240 // returns.
241 return dialog->RunDialogAndGetResult();
244 } // namespace
246 MessageBoxResult ShowMessageBox(gfx::NativeWindow parent,
247 const base::string16& title,
248 const base::string16& message,
249 MessageBoxType type) {
250 return ShowMessageBoxImpl(
251 parent, title, message, type, base::string16(), base::string16());
254 MessageBoxResult ShowMessageBoxWithButtonText(gfx::NativeWindow parent,
255 const base::string16& title,
256 const base::string16& message,
257 const base::string16& yes_text,
258 const base::string16& no_text) {
259 return ShowMessageBoxImpl(
260 parent, title, message, MESSAGE_BOX_TYPE_QUESTION, yes_text, no_text);
263 } // namespace chrome