simple_message_box_views.cc revision 9ab5563a3196760eb381d102cbb2bc0f7abc6a50
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/memory/ref_counted.h" 10#include "base/message_loop/message_loop.h" 11#include "base/run_loop.h" 12#include "chrome/browser/browser_process.h" 13#include "chrome/browser/ui/views/constrained_window_views.h" 14#include "grit/generated_resources.h" 15#include "ui/base/l10n/l10n_util.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(USE_AURA) 22#include "ui/aura/client/dispatcher_client.h" 23#include "ui/aura/env.h" 24#include "ui/aura/root_window.h" 25#endif 26 27namespace chrome { 28 29namespace { 30 31// Multiple SimpleMessageBoxViews can show up at the same time. Each of these 32// start a nested message-loop. However, these SimpleMessageBoxViews can be 33// deleted in any order. This creates problems if a box in an inner-loop gets 34// destroyed before a box in an outer-loop. So to avoid this, ref-counting is 35// used so that the SimpleMessageBoxViews gets deleted at the right time. 36class SimpleMessageBoxViews : public views::DialogDelegate, 37 public base::MessageLoop::Dispatcher, 38 public base::RefCounted<SimpleMessageBoxViews> { 39 public: 40 SimpleMessageBoxViews(const string16& title, 41 const string16& message, 42 MessageBoxType type); 43 44 MessageBoxResult result() const { return result_; } 45 46 // Overridden from views::DialogDelegate: 47 virtual int GetDialogButtons() const OVERRIDE; 48 virtual string16 GetDialogButtonLabel(ui::DialogButton button) const OVERRIDE; 49 virtual bool Cancel() OVERRIDE; 50 virtual bool Accept() OVERRIDE; 51 52 // Overridden from views::WidgetDelegate: 53 virtual string16 GetWindowTitle() const OVERRIDE; 54 virtual void DeleteDelegate() OVERRIDE; 55 virtual ui::ModalType GetModalType() const OVERRIDE; 56 virtual views::View* GetContentsView() OVERRIDE; 57 virtual views::Widget* GetWidget() OVERRIDE; 58 virtual const views::Widget* GetWidget() const OVERRIDE; 59 60 // Overridden from MessageLoop::Dispatcher: 61 virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE; 62 63 private: 64 friend class base::RefCounted<SimpleMessageBoxViews>; 65 virtual ~SimpleMessageBoxViews(); 66 67 const string16 window_title_; 68 const MessageBoxType type_; 69 MessageBoxResult result_; 70 views::MessageBoxView* message_box_view_; 71 72 // Set to false as soon as the user clicks a dialog button; this tells the 73 // dispatcher we're done. 74 bool should_show_dialog_; 75 76 DISALLOW_COPY_AND_ASSIGN(SimpleMessageBoxViews); 77}; 78 79//////////////////////////////////////////////////////////////////////////////// 80// SimpleMessageBoxViews, public: 81 82SimpleMessageBoxViews::SimpleMessageBoxViews(const string16& title, 83 const string16& message, 84 MessageBoxType type) 85 : window_title_(title), 86 type_(type), 87 result_(MESSAGE_BOX_RESULT_NO), 88 message_box_view_(new views::MessageBoxView( 89 views::MessageBoxView::InitParams(message))), 90 should_show_dialog_(true) { 91 AddRef(); 92} 93 94int SimpleMessageBoxViews::GetDialogButtons() const { 95 if (type_ == MESSAGE_BOX_TYPE_QUESTION || 96 type_ == MESSAGE_BOX_TYPE_OK_CANCEL) { 97 return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL; 98 } 99 100 return ui::DIALOG_BUTTON_OK; 101} 102 103string16 SimpleMessageBoxViews::GetDialogButtonLabel( 104 ui::DialogButton button) const { 105 if (type_ == MESSAGE_BOX_TYPE_QUESTION) { 106 return l10n_util::GetStringUTF16((button == ui::DIALOG_BUTTON_OK) ? 107 IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL : 108 IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL); 109 } 110 111 if (type_ == MESSAGE_BOX_TYPE_OK_CANCEL) { 112 return l10n_util::GetStringUTF16((button == ui::DIALOG_BUTTON_OK) ? 113 IDS_OK : IDS_CANCEL); 114 } 115 116 return l10n_util::GetStringUTF16(IDS_OK); 117} 118 119bool SimpleMessageBoxViews::Cancel() { 120 should_show_dialog_= false; 121 result_ = MESSAGE_BOX_RESULT_NO; 122 return true; 123} 124 125bool SimpleMessageBoxViews::Accept() { 126 should_show_dialog_ = false; 127 result_ = MESSAGE_BOX_RESULT_YES; 128 return true; 129} 130 131string16 SimpleMessageBoxViews::GetWindowTitle() const { 132 return window_title_; 133} 134 135void SimpleMessageBoxViews::DeleteDelegate() { 136 Release(); 137} 138 139ui::ModalType SimpleMessageBoxViews::GetModalType() const { 140 return ui::MODAL_TYPE_WINDOW; 141} 142 143views::View* SimpleMessageBoxViews::GetContentsView() { 144 return message_box_view_; 145} 146 147views::Widget* SimpleMessageBoxViews::GetWidget() { 148 return message_box_view_->GetWidget(); 149} 150 151const views::Widget* SimpleMessageBoxViews::GetWidget() const { 152 return message_box_view_->GetWidget(); 153} 154 155bool SimpleMessageBoxViews::Dispatch(const base::NativeEvent& event) { 156#if defined(OS_WIN) 157 TranslateMessage(&event); 158 DispatchMessage(&event); 159#elif defined(USE_AURA) 160 aura::Env::GetInstance()->GetDispatcher()->Dispatch(event); 161#endif 162 return should_show_dialog_; 163} 164 165//////////////////////////////////////////////////////////////////////////////// 166// SimpleMessageBoxViews, private: 167 168SimpleMessageBoxViews::~SimpleMessageBoxViews() { 169} 170 171} // namespace 172 173MessageBoxResult ShowMessageBox(gfx::NativeWindow parent, 174 const string16& title, 175 const string16& message, 176 MessageBoxType type) { 177 scoped_refptr<SimpleMessageBoxViews> dialog( 178 new SimpleMessageBoxViews(title, message, type)); 179 CreateBrowserModalDialogViews(dialog.get(), parent)->Show(); 180 181#if defined(USE_AURA) 182 // Use the widget's window itself so that the message loop 183 // exists when the dialog is closed by some other means than 184 // |Cancel| or |Accept|. 185 aura::Window* anchor = parent ? 186 parent : dialog->GetWidget()->GetNativeWindow(); 187 aura::client::GetDispatcherClient(anchor->GetRootWindow()) 188 ->RunWithDispatcher(dialog.get(), anchor, true); 189#else 190 { 191 base::MessageLoop::ScopedNestableTaskAllower allow( 192 base::MessageLoopForUI::current()); 193 base::RunLoop run_loop(dialog); 194 run_loop.Run(); 195 } 196#endif 197 return dialog->result(); 198} 199 200} // namespace chrome 201