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