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