Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / views / simple_message_box_views.cc
blob504337607b234845925b6cbf70e0dee66d6a7df4
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/browser/ui/simple_message_box_internal.h"
12 #include "chrome/grit/generated_resources.h"
13 #include "components/constrained_window/constrained_window_views.h"
14 #include "components/startup_metric_utils/startup_metric_utils.h"
15 #include "ui/base/l10n/l10n_util.h"
16 #include "ui/base/resource/resource_bundle.h"
17 #include "ui/gfx/native_widget_types.h"
18 #include "ui/views/controls/message_box_view.h"
19 #include "ui/views/widget/widget.h"
20 #include "ui/views/window/dialog_delegate.h"
22 #if defined(OS_WIN)
23 #include "ui/base/win/message_box_win.h"
24 #include "ui/views/win/hwnd_util.h"
25 #endif
27 namespace chrome {
29 namespace {
31 class SimpleMessageBoxViews : public views::DialogDelegate {
32 public:
33 SimpleMessageBoxViews(const base::string16& title,
34 const base::string16& message,
35 MessageBoxType type,
36 const base::string16& yes_text,
37 const base::string16& no_text,
38 bool is_system_modal);
39 ~SimpleMessageBoxViews() override;
41 MessageBoxResult RunDialogAndGetResult();
43 // Overridden from views::DialogDelegate:
44 int GetDialogButtons() const override;
45 base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
46 bool Cancel() override;
47 bool Accept() override;
49 // Overridden from views::WidgetDelegate:
50 base::string16 GetWindowTitle() const override;
51 void DeleteDelegate() override;
52 ui::ModalType GetModalType() const override;
53 views::View* GetContentsView() override;
54 views::Widget* GetWidget() override;
55 const views::Widget* GetWidget() const override;
57 private:
58 // This terminates the nested message-loop.
59 void Done();
61 const base::string16 window_title_;
62 const MessageBoxType type_;
63 base::string16 yes_text_;
64 base::string16 no_text_;
65 MessageBoxResult* result_;
66 bool is_system_modal_;
67 views::MessageBoxView* message_box_view_;
68 base::Closure quit_runloop_;
70 DISALLOW_COPY_AND_ASSIGN(SimpleMessageBoxViews);
73 ////////////////////////////////////////////////////////////////////////////////
74 // SimpleMessageBoxViews, public:
76 SimpleMessageBoxViews::SimpleMessageBoxViews(const base::string16& title,
77 const base::string16& message,
78 MessageBoxType type,
79 const base::string16& yes_text,
80 const base::string16& no_text,
81 bool is_system_modal)
82 : window_title_(title),
83 type_(type),
84 yes_text_(yes_text),
85 no_text_(no_text),
86 result_(NULL),
87 is_system_modal_(is_system_modal),
88 message_box_view_(new views::MessageBoxView(
89 views::MessageBoxView::InitParams(message))) {
90 if (yes_text_.empty()) {
91 if (type_ == MESSAGE_BOX_TYPE_QUESTION)
92 yes_text_ =
93 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL);
94 else if (type_ == MESSAGE_BOX_TYPE_OK_CANCEL)
95 yes_text_ = l10n_util::GetStringUTF16(IDS_OK);
96 else
97 yes_text_ = l10n_util::GetStringUTF16(IDS_OK);
100 if (no_text_.empty()) {
101 if (type_ == MESSAGE_BOX_TYPE_QUESTION)
102 no_text_ =
103 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL);
104 else if (type_ == MESSAGE_BOX_TYPE_OK_CANCEL)
105 no_text_ = l10n_util::GetStringUTF16(IDS_CANCEL);
109 SimpleMessageBoxViews::~SimpleMessageBoxViews() {
112 MessageBoxResult SimpleMessageBoxViews::RunDialogAndGetResult() {
113 MessageBoxResult result = MESSAGE_BOX_RESULT_NO;
114 result_ = &result;
115 // TODO(pkotwicz): Exit message loop when the dialog is closed by some other
116 // means than |Cancel| or |Accept|. crbug.com/404385
117 base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
118 base::MessageLoopForUI::ScopedNestableTaskAllower allow_nested(loop);
119 base::RunLoop run_loop;
120 quit_runloop_ = run_loop.QuitClosure();
121 run_loop.Run();
122 return result;
125 int SimpleMessageBoxViews::GetDialogButtons() const {
126 if (type_ == MESSAGE_BOX_TYPE_QUESTION ||
127 type_ == MESSAGE_BOX_TYPE_OK_CANCEL) {
128 return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL;
131 return ui::DIALOG_BUTTON_OK;
134 base::string16 SimpleMessageBoxViews::GetDialogButtonLabel(
135 ui::DialogButton button) const {
136 if (button == ui::DIALOG_BUTTON_CANCEL)
137 return no_text_;
138 return yes_text_;
141 bool SimpleMessageBoxViews::Cancel() {
142 *result_ = MESSAGE_BOX_RESULT_NO;
143 Done();
144 return true;
147 bool SimpleMessageBoxViews::Accept() {
148 *result_ = MESSAGE_BOX_RESULT_YES;
149 Done();
150 return true;
153 base::string16 SimpleMessageBoxViews::GetWindowTitle() const {
154 return window_title_;
157 void SimpleMessageBoxViews::DeleteDelegate() {
158 delete this;
161 ui::ModalType SimpleMessageBoxViews::GetModalType() const {
162 return is_system_modal_ ? ui::MODAL_TYPE_SYSTEM : ui::MODAL_TYPE_WINDOW;
165 views::View* SimpleMessageBoxViews::GetContentsView() {
166 return message_box_view_;
169 views::Widget* SimpleMessageBoxViews::GetWidget() {
170 return message_box_view_->GetWidget();
173 const views::Widget* SimpleMessageBoxViews::GetWidget() const {
174 return message_box_view_->GetWidget();
177 ////////////////////////////////////////////////////////////////////////////////
178 // SimpleMessageBoxViews, private:
180 void SimpleMessageBoxViews::Done() {
181 CHECK(!quit_runloop_.is_null());
182 quit_runloop_.Run();
185 #if defined(OS_WIN)
186 UINT GetMessageBoxFlagsFromType(MessageBoxType type) {
187 UINT flags = MB_SETFOREGROUND;
188 switch (type) {
189 case MESSAGE_BOX_TYPE_INFORMATION:
190 return flags | MB_OK | MB_ICONINFORMATION;
191 case MESSAGE_BOX_TYPE_WARNING:
192 return flags | MB_OK | MB_ICONWARNING;
193 case MESSAGE_BOX_TYPE_QUESTION:
194 return flags | MB_YESNO | MB_ICONQUESTION;
195 case MESSAGE_BOX_TYPE_OK_CANCEL:
196 return flags | MB_OKCANCEL | MB_ICONWARNING;
198 NOTREACHED();
199 return flags | MB_OK | MB_ICONWARNING;
201 #endif
203 MessageBoxResult ShowMessageBoxImpl(gfx::NativeWindow parent,
204 const base::string16& title,
205 const base::string16& message,
206 MessageBoxType type,
207 const base::string16& yes_text,
208 const base::string16& no_text) {
209 startup_metric_utils::SetNonBrowserUIDisplayed();
210 if (internal::g_should_skip_message_box_for_test)
211 return MESSAGE_BOX_RESULT_YES;
213 // Views dialogs cannot be shown outside the UI thread message loop or if the
214 // ResourceBundle is not initialized yet.
215 // Fallback to logging with a default response or a Windows MessageBox.
216 #if defined(OS_WIN)
217 if (!base::MessageLoopForUI::IsCurrent() ||
218 !base::MessageLoopForUI::current()->is_running() ||
219 !ResourceBundle::HasSharedInstance()) {
220 int result = ui::MessageBox(views::HWNDForNativeWindow(parent), message,
221 title, GetMessageBoxFlagsFromType(type));
222 return (result == IDYES || result == IDOK) ?
223 MESSAGE_BOX_RESULT_YES : MESSAGE_BOX_RESULT_NO;
225 #else
226 if (!base::MessageLoopForUI::IsCurrent() ||
227 !ResourceBundle::HasSharedInstance()) {
228 LOG(ERROR) << "Unable to show a dialog outside the UI thread message loop: "
229 << title << " - " << message;
230 return MESSAGE_BOX_RESULT_NO;
232 #endif
234 SimpleMessageBoxViews* dialog =
235 new SimpleMessageBoxViews(title,
236 message,
237 type,
238 yes_text,
239 no_text,
240 parent == NULL // is_system_modal
242 constrained_window::CreateBrowserModalDialogViews(dialog, parent)->Show();
244 // NOTE: |dialog| may have been deleted by the time |RunDialogAndGetResult()|
245 // returns.
246 return dialog->RunDialogAndGetResult();
249 } // namespace
251 MessageBoxResult ShowMessageBox(gfx::NativeWindow parent,
252 const base::string16& title,
253 const base::string16& message,
254 MessageBoxType type) {
255 return ShowMessageBoxImpl(
256 parent, title, message, type, base::string16(), base::string16());
259 MessageBoxResult ShowMessageBoxWithButtonText(gfx::NativeWindow parent,
260 const base::string16& title,
261 const base::string16& message,
262 const base::string16& yes_text,
263 const base::string16& no_text) {
264 return ShowMessageBoxImpl(
265 parent, title, message, MESSAGE_BOX_TYPE_QUESTION, yes_text, no_text);
268 } // namespace chrome