OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/simple_message_box.h" | 5 #include "chrome/browser/ui/simple_message_box.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/memory/ref_counted.h" | |
10 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
11 #include "chrome/browser/ui/views/constrained_window_views.h" | 10 #include "chrome/browser/ui/views/constrained_window_views.h" |
12 #include "grit/generated_resources.h" | 11 #include "grit/generated_resources.h" |
13 #include "ui/aura/window.h" | 12 #include "ui/aura/window.h" |
14 #include "ui/base/l10n/l10n_util.h" | 13 #include "ui/base/l10n/l10n_util.h" |
15 #include "ui/gfx/native_widget_types.h" | 14 #include "ui/gfx/native_widget_types.h" |
16 #include "ui/views/controls/message_box_view.h" | 15 #include "ui/views/controls/message_box_view.h" |
17 #include "ui/views/widget/widget.h" | 16 #include "ui/views/widget/widget.h" |
18 #include "ui/views/window/dialog_delegate.h" | 17 #include "ui/views/window/dialog_delegate.h" |
19 #include "ui/wm/public/dispatcher_client.h" | 18 #include "ui/wm/public/dispatcher_client.h" |
20 | 19 |
21 #if defined(OS_WIN) | 20 #if defined(OS_WIN) |
22 #include "ui/base/win/message_box_win.h" | 21 #include "ui/base/win/message_box_win.h" |
23 #include "ui/views/win/hwnd_util.h" | 22 #include "ui/views/win/hwnd_util.h" |
24 #endif | 23 #endif |
25 | 24 |
26 namespace chrome { | 25 namespace chrome { |
27 | 26 |
28 namespace { | 27 namespace { |
29 | 28 |
30 // Multiple SimpleMessageBoxViews can show up at the same time. Each of these | 29 class SimpleMessageBoxViews : public views::DialogDelegate { |
31 // start a nested message-loop. However, these SimpleMessageBoxViews can be | |
32 // deleted in any order. This creates problems if a box in an inner-loop gets | |
33 // destroyed before a box in an outer-loop. So to avoid this, ref-counting is | |
34 // used so that the SimpleMessageBoxViews gets deleted at the right time. | |
35 class SimpleMessageBoxViews : public views::DialogDelegate, | |
36 public base::RefCounted<SimpleMessageBoxViews> { | |
37 public: | 30 public: |
38 SimpleMessageBoxViews(const base::string16& title, | 31 SimpleMessageBoxViews(const base::string16& title, |
39 const base::string16& message, | 32 const base::string16& message, |
40 MessageBoxType type, | 33 MessageBoxType type, |
41 const base::string16& yes_text, | 34 const base::string16& yes_text, |
42 const base::string16& no_text); | 35 const base::string16& no_text, |
43 | 36 MessageBoxResult* result); |
44 MessageBoxResult result() const { return result_; } | 37 virtual ~SimpleMessageBoxViews(); |
45 | 38 |
46 // Overridden from views::DialogDelegate: | 39 // Overridden from views::DialogDelegate: |
47 virtual int GetDialogButtons() const OVERRIDE; | 40 virtual int GetDialogButtons() const OVERRIDE; |
48 virtual base::string16 GetDialogButtonLabel( | 41 virtual base::string16 GetDialogButtonLabel( |
49 ui::DialogButton button) const OVERRIDE; | 42 ui::DialogButton button) const OVERRIDE; |
50 virtual bool Cancel() OVERRIDE; | 43 virtual bool Cancel() OVERRIDE; |
51 virtual bool Accept() OVERRIDE; | 44 virtual bool Accept() OVERRIDE; |
52 | 45 |
53 // Overridden from views::WidgetDelegate: | 46 // Overridden from views::WidgetDelegate: |
54 virtual base::string16 GetWindowTitle() const OVERRIDE; | 47 virtual base::string16 GetWindowTitle() const OVERRIDE; |
55 virtual void DeleteDelegate() OVERRIDE; | 48 virtual void DeleteDelegate() OVERRIDE; |
56 virtual ui::ModalType GetModalType() const OVERRIDE; | 49 virtual ui::ModalType GetModalType() const OVERRIDE; |
57 virtual views::View* GetContentsView() OVERRIDE; | 50 virtual views::View* GetContentsView() OVERRIDE; |
58 virtual views::Widget* GetWidget() OVERRIDE; | 51 virtual views::Widget* GetWidget() OVERRIDE; |
59 virtual const views::Widget* GetWidget() const OVERRIDE; | 52 virtual const views::Widget* GetWidget() const OVERRIDE; |
60 | 53 |
61 private: | 54 private: |
62 friend class base::RefCounted<SimpleMessageBoxViews>; | |
63 virtual ~SimpleMessageBoxViews(); | |
64 | 55 |
65 // This terminates the nested message-loop. | 56 // This terminates the nested message-loop. |
66 void Done(); | 57 void Done(); |
67 | 58 |
68 const base::string16 window_title_; | 59 const base::string16 window_title_; |
69 const MessageBoxType type_; | 60 const MessageBoxType type_; |
70 base::string16 yes_text_; | 61 base::string16 yes_text_; |
71 base::string16 no_text_; | 62 base::string16 no_text_; |
72 MessageBoxResult result_; | 63 MessageBoxResult* result_; |
73 views::MessageBoxView* message_box_view_; | 64 views::MessageBoxView* message_box_view_; |
74 | 65 |
75 DISALLOW_COPY_AND_ASSIGN(SimpleMessageBoxViews); | 66 DISALLOW_COPY_AND_ASSIGN(SimpleMessageBoxViews); |
76 }; | 67 }; |
77 | 68 |
78 //////////////////////////////////////////////////////////////////////////////// | 69 //////////////////////////////////////////////////////////////////////////////// |
79 // SimpleMessageBoxViews, public: | 70 // SimpleMessageBoxViews, public: |
80 | 71 |
81 SimpleMessageBoxViews::SimpleMessageBoxViews(const base::string16& title, | 72 SimpleMessageBoxViews::SimpleMessageBoxViews(const base::string16& title, |
82 const base::string16& message, | 73 const base::string16& message, |
83 MessageBoxType type, | 74 MessageBoxType type, |
84 const base::string16& yes_text, | 75 const base::string16& yes_text, |
85 const base::string16& no_text) | 76 const base::string16& no_text, |
| 77 MessageBoxResult* result) |
86 : window_title_(title), | 78 : window_title_(title), |
87 type_(type), | 79 type_(type), |
88 yes_text_(yes_text), | 80 yes_text_(yes_text), |
89 no_text_(no_text), | 81 no_text_(no_text), |
90 result_(MESSAGE_BOX_RESULT_NO), | 82 result_(result), |
91 message_box_view_(new views::MessageBoxView( | 83 message_box_view_(new views::MessageBoxView( |
92 views::MessageBoxView::InitParams(message))) { | 84 views::MessageBoxView::InitParams(message))) { |
93 AddRef(); | 85 CHECK(result_); |
94 | |
95 if (yes_text_.empty()) { | 86 if (yes_text_.empty()) { |
96 if (type_ == MESSAGE_BOX_TYPE_QUESTION) | 87 if (type_ == MESSAGE_BOX_TYPE_QUESTION) |
97 yes_text_ = | 88 yes_text_ = |
98 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL); | 89 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL); |
99 else if (type_ == MESSAGE_BOX_TYPE_OK_CANCEL) | 90 else if (type_ == MESSAGE_BOX_TYPE_OK_CANCEL) |
100 yes_text_ = l10n_util::GetStringUTF16(IDS_OK); | 91 yes_text_ = l10n_util::GetStringUTF16(IDS_OK); |
101 else | 92 else |
102 yes_text_ = l10n_util::GetStringUTF16(IDS_OK); | 93 yes_text_ = l10n_util::GetStringUTF16(IDS_OK); |
103 } | 94 } |
104 | 95 |
105 if (no_text_.empty()) { | 96 if (no_text_.empty()) { |
106 if (type_ == MESSAGE_BOX_TYPE_QUESTION) | 97 if (type_ == MESSAGE_BOX_TYPE_QUESTION) |
107 no_text_ = | 98 no_text_ = |
108 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL); | 99 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL); |
109 else if (type_ == MESSAGE_BOX_TYPE_OK_CANCEL) | 100 else if (type_ == MESSAGE_BOX_TYPE_OK_CANCEL) |
110 no_text_ = l10n_util::GetStringUTF16(IDS_CANCEL); | 101 no_text_ = l10n_util::GetStringUTF16(IDS_CANCEL); |
111 } | 102 } |
112 } | 103 } |
113 | 104 |
| 105 SimpleMessageBoxViews::~SimpleMessageBoxViews() { |
| 106 } |
| 107 |
114 int SimpleMessageBoxViews::GetDialogButtons() const { | 108 int SimpleMessageBoxViews::GetDialogButtons() const { |
115 if (type_ == MESSAGE_BOX_TYPE_QUESTION || | 109 if (type_ == MESSAGE_BOX_TYPE_QUESTION || |
116 type_ == MESSAGE_BOX_TYPE_OK_CANCEL) { | 110 type_ == MESSAGE_BOX_TYPE_OK_CANCEL) { |
117 return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL; | 111 return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL; |
118 } | 112 } |
119 | 113 |
120 return ui::DIALOG_BUTTON_OK; | 114 return ui::DIALOG_BUTTON_OK; |
121 } | 115 } |
122 | 116 |
123 base::string16 SimpleMessageBoxViews::GetDialogButtonLabel( | 117 base::string16 SimpleMessageBoxViews::GetDialogButtonLabel( |
124 ui::DialogButton button) const { | 118 ui::DialogButton button) const { |
125 if (button == ui::DIALOG_BUTTON_CANCEL) | 119 if (button == ui::DIALOG_BUTTON_CANCEL) |
126 return no_text_; | 120 return no_text_; |
127 return yes_text_; | 121 return yes_text_; |
128 } | 122 } |
129 | 123 |
130 bool SimpleMessageBoxViews::Cancel() { | 124 bool SimpleMessageBoxViews::Cancel() { |
131 result_ = MESSAGE_BOX_RESULT_NO; | 125 *result_ = MESSAGE_BOX_RESULT_NO; |
132 Done(); | 126 Done(); |
133 return true; | 127 return true; |
134 } | 128 } |
135 | 129 |
136 bool SimpleMessageBoxViews::Accept() { | 130 bool SimpleMessageBoxViews::Accept() { |
137 result_ = MESSAGE_BOX_RESULT_YES; | 131 *result_ = MESSAGE_BOX_RESULT_YES; |
138 Done(); | 132 Done(); |
139 return true; | 133 return true; |
140 } | 134 } |
141 | 135 |
142 base::string16 SimpleMessageBoxViews::GetWindowTitle() const { | 136 base::string16 SimpleMessageBoxViews::GetWindowTitle() const { |
143 return window_title_; | 137 return window_title_; |
144 } | 138 } |
145 | 139 |
146 void SimpleMessageBoxViews::DeleteDelegate() { | 140 void SimpleMessageBoxViews::DeleteDelegate() { |
147 Release(); | 141 delete this; |
148 } | 142 } |
149 | 143 |
150 ui::ModalType SimpleMessageBoxViews::GetModalType() const { | 144 ui::ModalType SimpleMessageBoxViews::GetModalType() const { |
151 return ui::MODAL_TYPE_WINDOW; | 145 return ui::MODAL_TYPE_WINDOW; |
152 } | 146 } |
153 | 147 |
154 views::View* SimpleMessageBoxViews::GetContentsView() { | 148 views::View* SimpleMessageBoxViews::GetContentsView() { |
155 return message_box_view_; | 149 return message_box_view_; |
156 } | 150 } |
157 | 151 |
158 views::Widget* SimpleMessageBoxViews::GetWidget() { | 152 views::Widget* SimpleMessageBoxViews::GetWidget() { |
159 return message_box_view_->GetWidget(); | 153 return message_box_view_->GetWidget(); |
160 } | 154 } |
161 | 155 |
162 const views::Widget* SimpleMessageBoxViews::GetWidget() const { | 156 const views::Widget* SimpleMessageBoxViews::GetWidget() const { |
163 return message_box_view_->GetWidget(); | 157 return message_box_view_->GetWidget(); |
164 } | 158 } |
165 | 159 |
166 //////////////////////////////////////////////////////////////////////////////// | 160 //////////////////////////////////////////////////////////////////////////////// |
167 // SimpleMessageBoxViews, private: | 161 // SimpleMessageBoxViews, private: |
168 | 162 |
169 SimpleMessageBoxViews::~SimpleMessageBoxViews() { | |
170 } | |
171 | |
172 void SimpleMessageBoxViews::Done() { | 163 void SimpleMessageBoxViews::Done() { |
173 aura::Window* window = GetWidget()->GetNativeView(); | 164 aura::Window* window = GetWidget()->GetNativeView(); |
174 aura::client::DispatcherClient* client = | 165 aura::client::DispatcherClient* client = |
175 aura::client::GetDispatcherClient(window->GetRootWindow()); | 166 aura::client::GetDispatcherClient(window->GetRootWindow()); |
176 client->QuitNestedMessageLoop(); | 167 client->QuitNestedMessageLoop(); |
177 } | 168 } |
178 | 169 |
179 #if defined(OS_WIN) | 170 #if defined(OS_WIN) |
180 UINT GetMessageBoxFlagsFromType(MessageBoxType type) { | 171 UINT GetMessageBoxFlagsFromType(MessageBoxType type) { |
181 UINT flags = MB_SETFOREGROUND; | 172 UINT flags = MB_SETFOREGROUND; |
(...skipping 21 matching lines...) Expand all Loading... |
203 #if defined(OS_WIN) | 194 #if defined(OS_WIN) |
204 // GPU-based dialogs can't be used early on; fallback to a Windows MessageBox. | 195 // GPU-based dialogs can't be used early on; fallback to a Windows MessageBox. |
205 if (!base::MessageLoop::current()->is_running()) { | 196 if (!base::MessageLoop::current()->is_running()) { |
206 int result = ui::MessageBox(views::HWNDForNativeWindow(parent), message, | 197 int result = ui::MessageBox(views::HWNDForNativeWindow(parent), message, |
207 title, GetMessageBoxFlagsFromType(type)); | 198 title, GetMessageBoxFlagsFromType(type)); |
208 return (result == IDYES || result == IDOK) ? | 199 return (result == IDYES || result == IDOK) ? |
209 MESSAGE_BOX_RESULT_YES : MESSAGE_BOX_RESULT_NO; | 200 MESSAGE_BOX_RESULT_YES : MESSAGE_BOX_RESULT_NO; |
210 } | 201 } |
211 #endif | 202 #endif |
212 | 203 |
213 scoped_refptr<SimpleMessageBoxViews> dialog( | 204 MessageBoxResult result = MESSAGE_BOX_RESULT_NO; |
214 new SimpleMessageBoxViews(title, message, type, yes_text, no_text)); | 205 SimpleMessageBoxViews* dialog = new SimpleMessageBoxViews( |
215 CreateBrowserModalDialogViews(dialog.get(), parent)->Show(); | 206 title, message, type, yes_text, no_text, &result); |
| 207 CreateBrowserModalDialogViews(dialog, parent)->Show(); |
216 | 208 |
217 // Use the widget's window itself so that the message loop | 209 // Use the widget's window itself so that the message loop |
218 // exists when the dialog is closed by some other means than | 210 // exists when the dialog is closed by some other means than |
219 // |Cancel| or |Accept|. | 211 // |Cancel| or |Accept|. |
220 aura::Window* anchor = dialog->GetWidget()->GetNativeWindow(); | 212 aura::Window* anchor = dialog->GetWidget()->GetNativeWindow(); |
221 aura::client::DispatcherClient* client = | 213 aura::client::DispatcherClient* client = |
222 aura::client::GetDispatcherClient(anchor->GetRootWindow()); | 214 aura::client::GetDispatcherClient(anchor->GetRootWindow()); |
223 client->RunWithDispatcher(NULL); | 215 client->RunWithDispatcher(NULL); |
224 return dialog->result(); | 216 // NOTE: |dialog| will have been deleted by the time control returns here. |
| 217 |
| 218 return result; |
225 } | 219 } |
226 | 220 |
227 } // namespace | 221 } // namespace |
228 | 222 |
229 MessageBoxResult ShowMessageBox(gfx::NativeWindow parent, | 223 MessageBoxResult ShowMessageBox(gfx::NativeWindow parent, |
230 const base::string16& title, | 224 const base::string16& title, |
231 const base::string16& message, | 225 const base::string16& message, |
232 MessageBoxType type) { | 226 MessageBoxType type) { |
233 return ShowMessageBoxImpl( | 227 return ShowMessageBoxImpl( |
234 parent, title, message, type, base::string16(), base::string16()); | 228 parent, title, message, type, base::string16(), base::string16()); |
235 } | 229 } |
236 | 230 |
237 MessageBoxResult ShowMessageBoxWithButtonText(gfx::NativeWindow parent, | 231 MessageBoxResult ShowMessageBoxWithButtonText(gfx::NativeWindow parent, |
238 const base::string16& title, | 232 const base::string16& title, |
239 const base::string16& message, | 233 const base::string16& message, |
240 const base::string16& yes_text, | 234 const base::string16& yes_text, |
241 const base::string16& no_text) { | 235 const base::string16& no_text) { |
242 return ShowMessageBoxImpl( | 236 return ShowMessageBoxImpl( |
243 parent, title, message, MESSAGE_BOX_TYPE_QUESTION, yes_text, no_text); | 237 parent, title, message, MESSAGE_BOX_TYPE_QUESTION, yes_text, no_text); |
244 } | 238 } |
245 | 239 |
246 } // namespace chrome | 240 } // namespace chrome |
OLD | NEW |