Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / simple_message_box_views.cc
index b064069..9838fa7 100644 (file)
@@ -6,48 +6,38 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_pump_dispatcher.h"
-#include "base/run_loop.h"
-#include "chrome/browser/browser_process.h"
 #include "chrome/browser/ui/views/constrained_window_views.h"
-#include "grit/generated_resources.h"
+#include "chrome/grit/generated_resources.h"
+#include "ui/aura/window.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/views/controls/message_box_view.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/dialog_delegate.h"
+#include "ui/wm/public/dispatcher_client.h"
 
-#if defined(USE_AURA)
-#include "ui/aura/client/dispatcher_client.h"
-#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
 #if defined(OS_WIN)
-#include "chrome/browser/ui/views/simple_message_box_win.h"
-#endif
+#include "ui/base/win/message_box_win.h"
+#include "ui/views/win/hwnd_util.h"
 #endif
 
 namespace chrome {
 
 namespace {
 
-// Multiple SimpleMessageBoxViews can show up at the same time. Each of these
-// start a nested message-loop. However, these SimpleMessageBoxViews can be
-// deleted in any order. This creates problems if a box in an inner-loop gets
-// destroyed before a box in an outer-loop. So to avoid this, ref-counting is
-// used so that the SimpleMessageBoxViews gets deleted at the right time.
-class SimpleMessageBoxViews : public views::DialogDelegate,
-                              public base::MessagePumpDispatcher,
-                              public base::RefCounted<SimpleMessageBoxViews> {
+class SimpleMessageBoxViews : public views::DialogDelegate {
  public:
   SimpleMessageBoxViews(const base::string16& title,
                         const base::string16& message,
                         MessageBoxType type,
                         const base::string16& yes_text,
-                        const base::string16& no_text);
+                        const base::string16& no_text,
+                        bool is_system_modal);
+  virtual ~SimpleMessageBoxViews();
 
-  MessageBoxResult result() const { return result_; }
+  MessageBoxResult RunDialogAndGetResult();
 
   // Overridden from views::DialogDelegate:
   virtual int GetDialogButtons() const OVERRIDE;
@@ -64,23 +54,19 @@ class SimpleMessageBoxViews : public views::DialogDelegate,
   virtual views::Widget* GetWidget() OVERRIDE;
   virtual const views::Widget* GetWidget() const OVERRIDE;
 
-  // Overridden from MessagePumpDispatcher:
-  virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;
-
  private:
-  friend class base::RefCounted<SimpleMessageBoxViews>;
-  virtual ~SimpleMessageBoxViews();
+
+  // This terminates the nested message-loop.
+  void Done();
 
   const base::string16 window_title_;
   const MessageBoxType type_;
   base::string16 yes_text_;
   base::string16 no_text_;
-  MessageBoxResult result_;
+  MessageBoxResult* result_;
+  bool is_system_modal_;
   views::MessageBoxView* message_box_view_;
-
-  // Set to false as soon as the user clicks a dialog button; this tells the
-  // dispatcher we're done.
-  bool should_show_dialog_;
+  base::Closure quit_runloop_;
 
   DISALLOW_COPY_AND_ASSIGN(SimpleMessageBoxViews);
 };
@@ -92,17 +78,16 @@ SimpleMessageBoxViews::SimpleMessageBoxViews(const base::string16& title,
                                              const base::string16& message,
                                              MessageBoxType type,
                                              const base::string16& yes_text,
-                                             const base::string16& no_text)
+                                             const base::string16& no_text,
+                                             bool is_system_modal)
     : window_title_(title),
       type_(type),
       yes_text_(yes_text),
       no_text_(no_text),
-      result_(MESSAGE_BOX_RESULT_NO),
+      result_(NULL),
+      is_system_modal_(is_system_modal),
       message_box_view_(new views::MessageBoxView(
-          views::MessageBoxView::InitParams(message))),
-      should_show_dialog_(true) {
-  AddRef();
-
+          views::MessageBoxView::InitParams(message))) {
   if (yes_text_.empty()) {
     if (type_ == MESSAGE_BOX_TYPE_QUESTION)
       yes_text_ =
@@ -122,6 +107,22 @@ SimpleMessageBoxViews::SimpleMessageBoxViews(const base::string16& title,
   }
 }
 
+SimpleMessageBoxViews::~SimpleMessageBoxViews() {
+}
+
+MessageBoxResult SimpleMessageBoxViews::RunDialogAndGetResult() {
+  MessageBoxResult result = MESSAGE_BOX_RESULT_NO;
+  result_ = &result;
+  // Use the widget's window itself so that the message loop exists when the
+  // dialog is closed by some other means than |Cancel| or |Accept|.
+  aura::Window* anchor = GetWidget()->GetNativeWindow();
+  aura::client::DispatcherRunLoop run_loop(
+      aura::client::GetDispatcherClient(anchor->GetRootWindow()), NULL);
+  quit_runloop_ = run_loop.QuitClosure();
+  run_loop.Run();
+  return result;
+}
+
 int SimpleMessageBoxViews::GetDialogButtons() const {
   if (type_ == MESSAGE_BOX_TYPE_QUESTION ||
       type_ == MESSAGE_BOX_TYPE_OK_CANCEL) {
@@ -139,14 +140,14 @@ base::string16 SimpleMessageBoxViews::GetDialogButtonLabel(
 }
 
 bool SimpleMessageBoxViews::Cancel() {
-  should_show_dialog_= false;
-  result_ = MESSAGE_BOX_RESULT_NO;
+  *result_ = MESSAGE_BOX_RESULT_NO;
+  Done();
   return true;
 }
 
 bool SimpleMessageBoxViews::Accept() {
-  should_show_dialog_ = false;
-  result_ = MESSAGE_BOX_RESULT_YES;
+  *result_ = MESSAGE_BOX_RESULT_YES;
+  Done();
   return true;
 }
 
@@ -155,11 +156,11 @@ base::string16 SimpleMessageBoxViews::GetWindowTitle() const {
 }
 
 void SimpleMessageBoxViews::DeleteDelegate() {
-  Release();
+  delete this;
 }
 
 ui::ModalType SimpleMessageBoxViews::GetModalType() const {
-  return ui::MODAL_TYPE_WINDOW;
+  return is_system_modal_ ? ui::MODAL_TYPE_SYSTEM : ui::MODAL_TYPE_WINDOW;
 }
 
 views::View* SimpleMessageBoxViews::GetContentsView() {
@@ -174,21 +175,31 @@ const views::Widget* SimpleMessageBoxViews::GetWidget() const {
   return message_box_view_->GetWidget();
 }
 
-bool SimpleMessageBoxViews::Dispatch(const base::NativeEvent& event) {
-#if defined(OS_WIN)
-  TranslateMessage(&event);
-  DispatchMessage(&event);
-#elif defined(USE_AURA)
-  aura::Env::GetInstance()->GetDispatcher()->Dispatch(event);
-#endif
-  return should_show_dialog_;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // SimpleMessageBoxViews, private:
 
-SimpleMessageBoxViews::~SimpleMessageBoxViews() {
+void SimpleMessageBoxViews::Done() {
+  CHECK(!quit_runloop_.is_null());
+  quit_runloop_.Run();
+}
+
+#if defined(OS_WIN)
+UINT GetMessageBoxFlagsFromType(MessageBoxType type) {
+  UINT flags = MB_SETFOREGROUND;
+  switch (type) {
+    case MESSAGE_BOX_TYPE_INFORMATION:
+      return flags | MB_OK | MB_ICONINFORMATION;
+    case MESSAGE_BOX_TYPE_WARNING:
+      return flags | MB_OK | MB_ICONWARNING;
+    case MESSAGE_BOX_TYPE_QUESTION:
+      return flags | MB_YESNO | MB_ICONQUESTION;
+    case MESSAGE_BOX_TYPE_OK_CANCEL:
+      return flags | MB_OKCANCEL | MB_ICONWARNING;
+  }
+  NOTREACHED();
+  return flags | MB_OK | MB_ICONWARNING;
 }
+#endif
 
 MessageBoxResult ShowMessageBoxImpl(gfx::NativeWindow parent,
                                     const base::string16& title,
@@ -196,39 +207,40 @@ MessageBoxResult ShowMessageBoxImpl(gfx::NativeWindow parent,
                                     MessageBoxType type,
                                     const base::string16& yes_text,
                                     const base::string16& no_text) {
-
-#if defined(USE_AURA) && defined(OS_WIN)
-  // If we're very early, we can't show a GPU-based dialog, so fallback to
-  // plain Windows MessageBox.
-  if (!ui::ContextFactory::GetInstance())
-    return NativeShowMessageBox(NULL, title, message, type);
-#endif
-
-  scoped_refptr<SimpleMessageBoxViews> dialog(
-      new SimpleMessageBoxViews(title, message, type, yes_text, no_text));
-  CreateBrowserModalDialogViews(dialog.get(), parent)->Show();
-
-#if defined(USE_AURA)
-  aura::Window* anchor = parent;
-  aura::client::DispatcherClient* client = anchor ?
-      aura::client::GetDispatcherClient(anchor->GetRootWindow()) : NULL;
-  if (!client) {
-    // Use the widget's window itself so that the message loop
-    // exists when the dialog is closed by some other means than
-    // |Cancel| or |Accept|.
-    anchor = dialog->GetWidget()->GetNativeWindow();
-    client = aura::client::GetDispatcherClient(anchor->GetRootWindow());
+  // Views dialogs cannot be shown outside the UI thread message loop or if the
+  // ResourceBundle is not initialized yet.
+  // Fallback to logging with a default response or a Windows MessageBox.
+#if defined(OS_WIN)
+  if (!base::MessageLoopForUI::IsCurrent() ||
+      !base::MessageLoopForUI::current()->is_running() ||
+      !ResourceBundle::HasSharedInstance()) {
+    int result = ui::MessageBox(views::HWNDForNativeWindow(parent), message,
+                                title, GetMessageBoxFlagsFromType(type));
+    return (result == IDYES || result == IDOK) ?
+        MESSAGE_BOX_RESULT_YES : MESSAGE_BOX_RESULT_NO;
   }
-  client->RunWithDispatcher(dialog.get(), anchor, true);
 #else
-  {
-    base::MessageLoop::ScopedNestableTaskAllower allow(
-        base::MessageLoopForUI::current());
-    base::RunLoop run_loop(dialog);
-    run_loop.Run();
+  if (!base::MessageLoopForUI::IsCurrent() ||
+      !ResourceBundle::HasSharedInstance()) {
+    LOG(ERROR) << "Unable to show a dialog outside the UI thread message loop: "
+               << title << " - " << message;
+    return MESSAGE_BOX_RESULT_NO;
   }
 #endif
-  return dialog->result();
+
+  SimpleMessageBoxViews* dialog =
+      new SimpleMessageBoxViews(title,
+                                message,
+                                type,
+                                yes_text,
+                                no_text,
+                                parent == NULL  // is_system_modal
+                                );
+  CreateBrowserModalDialogViews(dialog, parent)->Show();
+
+  // NOTE: |dialog| may have been deleted by the time |RunDialogAndGetResult()|
+  // returns.
+  return dialog->RunDialogAndGetResult();
 }
 
 }  // namespace
@@ -241,7 +253,6 @@ MessageBoxResult ShowMessageBox(gfx::NativeWindow parent,
       parent, title, message, type, base::string16(), base::string16());
 }
 
-#if defined(USE_AURA)
 MessageBoxResult ShowMessageBoxWithButtonText(gfx::NativeWindow parent,
                                               const base::string16& title,
                                               const base::string16& message,
@@ -250,6 +261,5 @@ MessageBoxResult ShowMessageBoxWithButtonText(gfx::NativeWindow parent,
   return ShowMessageBoxImpl(
       parent, title, message, MESSAGE_BOX_TYPE_QUESTION, yes_text, no_text);
 }
-#endif
 
 }  // namespace chrome