win: Implement asynchronous ShowMessageBox.
authorCheng Zhao <zcbenz@gmail.com>
Tue, 24 Sep 2013 08:11:23 +0000 (16:11 +0800)
committerCheng Zhao <zcbenz@gmail.com>
Tue, 24 Sep 2013 08:11:23 +0000 (16:11 +0800)
browser/ui/message_box_win.cc

index 99da31f..68267c6 100644 (file)
@@ -39,7 +39,14 @@ class MessageDialog : public base::MessageLoop::Dispatcher,
                 const std::string& detail);
   virtual ~MessageDialog();
 
-  int result() const { return result_; }
+  void Show();
+
+  int GetResult() const;
+
+  void set_callback(const MessageBoxCallback& callback) {
+    delete_on_close_ = true;
+    callback_ = callback;
+  }
 
  private:
   // Overridden from MessageLoop::Dispatcher:
@@ -64,11 +71,13 @@ class MessageDialog : public base::MessageLoop::Dispatcher,
                              const ui::Event& event) OVERRIDE;
 
   bool should_close_;
+  bool delete_on_close_;
   int result_;
   string16 title_;
   views::Widget* widget_;
   views::MessageBoxView* message_box_view_;
   std::vector<views::LabelButton*> buttons_;
+  MessageBoxCallback callback_;
 
   DISALLOW_COPY_AND_ASSIGN(MessageDialog);
 };
@@ -83,6 +92,7 @@ MessageDialog::MessageDialog(NativeWindow* parent_window,
                              const std::string& message,
                              const std::string& detail)
     : should_close_(false),
+      delete_on_close_(false),
       result_(-1),
       title_(UTF8ToUTF16(title)),
       widget_(NULL),
@@ -125,12 +135,30 @@ MessageDialog::MessageDialog(NativeWindow* parent_window,
 
   set_background(views::Background::CreateSolidBackground(
         skia::COLORREFToSkColor(GetSysColor(COLOR_WINDOW))));
-  widget_->Show();
 }
 
 MessageDialog::~MessageDialog() {
 }
 
+void MessageDialog::Show() {
+  widget_->Show();
+}
+
+int MessageDialog::GetResult() const {
+  // When the dialog is closed without choosing anything, we think the user
+  // chose 'Cancel', otherwise we think the default behavior is chosen.
+  if (result_ == -1) {
+    for (size_t i = 0; i < buttons_.size(); ++i)
+      if (LowerCaseEqualsASCII(buttons_[i]->GetText(), "cancel")) {
+        return i;
+      }
+
+    return 0;
+  } else {
+    return result_;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // MessageDialog, private:
 
@@ -146,6 +174,11 @@ string16 MessageDialog::GetWindowTitle() const {
 
 void MessageDialog::WindowClosing() {
   should_close_ = true;
+
+  if (delete_on_close_) {
+    callback_.Run(GetResult());
+    base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+  }
 }
 
 views::Widget* MessageDialog::GetWidget() {
@@ -233,6 +266,7 @@ int ShowMessageBox(NativeWindow* parent_window,
                    const std::string& message,
                    const std::string& detail) {
   MessageDialog dialog(parent_window, type, buttons, title, message, detail);
+  dialog.Show();
   {
     base::MessageLoop::ScopedNestableTaskAllower allow(
         base::MessageLoopForUI::current());
@@ -240,18 +274,7 @@ int ShowMessageBox(NativeWindow* parent_window,
     run_loop.Run();
   }
 
-  // When the dialog is closed without choosing anything, we think the user
-  // chose 'Cancel', otherwise we think the default behavior is chosen.
-  if (dialog.result() == -1) {
-    for (size_t i = 0; i < buttons.size(); ++i)
-      if (LowerCaseEqualsASCII(buttons[i], "cancel")) {
-        return i;
-      }
-
-    return 0;
-  } else {
-    return dialog.result();
-  }
+  return dialog.GetResult();
 }
 
 void ShowMessageBox(NativeWindow* parent_window,
@@ -261,8 +284,11 @@ void ShowMessageBox(NativeWindow* parent_window,
                     const std::string& message,
                     const std::string& detail,
                     const MessageBoxCallback& callback) {
-  callback.Run(ShowMessageBox(
-      parent_window, type, buttons, title, message, detail));
+  // The dialog would be deleted when the dialog is closed.
+  MessageDialog* dialog = new MessageDialog(
+      parent_window, type, buttons, title, message, detail);
+  dialog->set_callback(callback);
+  dialog->Show();
 }
 
 }  // namespace atom