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