Chromium Code Reviews| Index: remoting/host/chromeos/message_box.cc |
| diff --git a/remoting/host/chromeos/message_box.cc b/remoting/host/chromeos/message_box.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..724cf48de52d652b8c486d9dcf89d2ee75adb391 |
| --- /dev/null |
| +++ b/remoting/host/chromeos/message_box.cc |
| @@ -0,0 +1,194 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "remoting/host/chromeos/message_box.h" |
| + |
| +#include "ui/base/l10n/l10n_util.h" |
| +#include "ui/views/controls/message_box_view.h" |
| +#include "ui/views/widget/widget.h" |
| +#include "ui/views/window/dialog_delegate.h" |
| + |
| +namespace remoting { |
| + |
| +// MessageBox::Core creates the dialog using the views::DialogWidget. The |
| +// DialogWidget is created by the caller but its lifetime is managed by the |
| +// NativeWidget. The DialogWidget communicates with the caller using the |
| +//.DialogDelegateView interface, which must remain valid until DeleteDelegate() |
| +// is called, at which the DialogDelegateView deletes itself. |
| +// |
| +// The Core class is introduced to abstract this awkward ownership model. The |
| +// Core and the MessageBox hold a raw references to each other, which is |
|
Wez
2014/11/04 19:10:20
nit: s/is/are
kelvinp
2014/11/04 19:28:27
Done.
|
| +// invalidated when either side is destroyed. |
| +class MessageBox::Core : public views::DialogDelegateView { |
| + public: |
| + Core(const base::string16& title_label, |
| + const base::string16& message_label, |
| + const base::string16& ok_label, |
| + const base::string16& cancel_label, |
| + ResultCallback result_callback, |
| + MessageBox* message_box); |
| + |
| + // Mirrors the MessageBox::Core interface |
|
Wez
2014/11/04 19:10:20
You mean mirrors the public MessageBox interface?
kelvinp
2014/11/04 19:28:27
Done.
|
| + void Show(); |
| + void Hide(); |
| + |
| + // views::DialogDelegateView interface. |
| + bool Accept() override; |
| + bool Cancel() override; |
| + ui::ModalType GetModalType() const override; |
| + base::string16 GetWindowTitle() const override; |
| + base::string16 GetDialogButtonLabel(ui::DialogButton button) const override; |
| + |
| + // views::WidgetDelegate interface. |
| + views::View* GetContentsView() override; |
| + views::Widget* GetWidget() override; |
| + const views::Widget* GetWidget() const override; |
| + void DeleteDelegate() override; |
| + |
| + // Called by MessageBox::Core when it is destroyed. |
| + void OnMessageBoxDestroyed(); |
| + |
| + private: |
| + const base::string16 title_label_; |
| + const base::string16 ok_label_; |
| + const base::string16 cancel_label_; |
| + ResultCallback result_callback_; |
| + MessageBox* message_box_; |
| + |
| + // Owned by the native widget hierarchy. |
| + views::MessageBoxView* message_box_view_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Core); |
| +}; |
| + |
| +MessageBox::Core::Core(const base::string16& title_label, |
| + const base::string16& message_label, |
| + const base::string16& ok_label, |
| + const base::string16& cancel_label, |
| + ResultCallback result_callback, |
| + MessageBox* message_box) |
| + : title_label_(title_label), |
| + ok_label_(ok_label), |
| + cancel_label_(cancel_label), |
| + result_callback_(result_callback), |
| + message_box_(message_box), |
| + message_box_view_(new views::MessageBoxView( |
| + views::MessageBoxView::InitParams(message_label))) { |
| + DCHECK(message_box_); |
| +} |
| + |
| +void MessageBox::Core::Show() { |
| + // The widget is owned by the NativeWidget. See comments in widget.h. |
| + views::Widget* widget = |
| + CreateDialogWidget(this, /* delegate */ |
| + nullptr /* parent window*/, |
| + nullptr /* parent view */); |
| + |
| + if (widget) { |
| + widget->Show(); |
| + } |
| +} |
| + |
| +void MessageBox::Core::Hide() { |
| + if (GetWidget()) { |
| + GetWidget()->Close(); |
| + } |
| +} |
| + |
| +bool MessageBox::Core::Accept() { |
| + if (!result_callback_.is_null()) { |
| + base::ResetAndReturn(&result_callback_).Run(OK); |
| + } |
| + return true /* close the window*/; |
| +} |
| + |
| +bool MessageBox::Core::Cancel() { |
| + if (!result_callback_.is_null()) { |
| + base::ResetAndReturn(&result_callback_).Run(CANCEL); |
| + } |
| + return true /* close the window*/; |
| +} |
| + |
| +ui::ModalType MessageBox::Core::GetModalType() const { |
| + return ui::MODAL_TYPE_SYSTEM; |
| +} |
| + |
| +base::string16 MessageBox::Core::GetWindowTitle() const { |
| + return title_label_; |
| +} |
| + |
| +base::string16 MessageBox::Core::GetDialogButtonLabel( |
| + ui::DialogButton button) const { |
| + switch (button) { |
| + case ui::DIALOG_BUTTON_OK: |
| + return ok_label_; |
| + case ui::DIALOG_BUTTON_CANCEL: |
| + return cancel_label_; |
| + default: |
| + NOTREACHED(); |
| + return base::string16(); |
| + } |
| +} |
| + |
| +views::View* MessageBox::Core::GetContentsView() { |
| + return message_box_view_; |
| +} |
| + |
| +views::Widget* MessageBox::Core::GetWidget() { |
| + return message_box_view_->GetWidget(); |
| +} |
| + |
| +const views::Widget* MessageBox::Core::GetWidget() const { |
| + return message_box_view_->GetWidget(); |
| +} |
| + |
| +void MessageBox::Core::DeleteDelegate() { |
| + if (message_box_) { |
| + message_box_->core_ = nullptr; |
| + } |
| + delete this; |
| +} |
| + |
| +void MessageBox::Core::OnMessageBoxDestroyed() { |
| + DCHECK(message_box_); |
| + message_box_ = nullptr; |
| + // The callback should not be invoked after MessageBox is destroyed. |
| + result_callback_.Reset(); |
| +} |
| + |
| +MessageBox::MessageBox(const base::string16& title_label, |
| + const base::string16& message_label, |
| + const base::string16& ok_label, |
| + const base::string16& cancel_label, |
| + ResultCallback result_callback) |
| + : core_(new Core(title_label, |
| + message_label, |
| + ok_label, |
| + cancel_label, |
| + result_callback, |
| + this)) { |
| + thread_checker_.DetachFromThread(); |
| +} |
| + |
| +MessageBox::~MessageBox() { |
| + if (core_) { |
| + core_->OnMessageBoxDestroyed(); |
| + core_->Hide(); |
| + core_ = nullptr; |
| + } |
| +} |
| + |
| +void MessageBox::Show() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + core_->Show(); |
| +} |
| + |
| +void MessageBox::Hide() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + if (core_) { |
| + core_->Hide(); |
| + } |
| +} |
| + |
| +} // namespace remoting |