| 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 |