message_box.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // Copyright 2014 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. #include "remoting/host/chromeos/message_box.h"
  5. #include <utility>
  6. #include "ui/base/l10n/l10n_util.h"
  7. #include "ui/base/metadata/metadata_header_macros.h"
  8. #include "ui/base/metadata/metadata_impl_macros.h"
  9. #include "ui/views/controls/message_box_view.h"
  10. #include "ui/views/widget/widget.h"
  11. #include "ui/views/window/dialog_delegate.h"
  12. namespace remoting {
  13. // MessageBox::Core creates the dialog using the views::DialogWidget. The
  14. // DialogWidget is created by the caller but its lifetime is managed by the
  15. // NativeWidget. The DialogWidget communicates with the caller using the
  16. // DialogDelegateView interface, which must remain valid until DeleteDelegate()
  17. // is called, at which the DialogDelegateView deletes itself.
  18. //
  19. // The Core class is introduced to abstract this awkward ownership model. The
  20. // Core and the MessageBox hold a raw references to each other, which is
  21. // invalidated when either side are destroyed.
  22. class MessageBox::Core : public views::DialogDelegateView {
  23. public:
  24. METADATA_HEADER(Core);
  25. Core(const std::u16string& title_label,
  26. const std::u16string& message_label,
  27. const std::u16string& ok_label,
  28. const std::u16string& cancel_label,
  29. ResultCallback result_callback,
  30. MessageBox* message_box);
  31. Core(const Core&) = delete;
  32. Core& operator=(const Core&) = delete;
  33. // Mirrors the public MessageBox interface.
  34. void Show();
  35. void Hide();
  36. // views::DialogDelegateView:
  37. ui::ModalType GetModalType() const override;
  38. std::u16string GetWindowTitle() const override;
  39. views::View* GetContentsView() override;
  40. views::Widget* GetWidget() override;
  41. const views::Widget* GetWidget() const override;
  42. // Called by MessageBox::Core when it is destroyed.
  43. void OnMessageBoxDestroyed();
  44. private:
  45. const std::u16string title_label_;
  46. ResultCallback result_callback_;
  47. MessageBox* message_box_;
  48. // Owned by the native widget hierarchy.
  49. views::MessageBoxView* message_box_view_;
  50. };
  51. MessageBox::Core::Core(const std::u16string& title_label,
  52. const std::u16string& message_label,
  53. const std::u16string& ok_label,
  54. const std::u16string& cancel_label,
  55. ResultCallback result_callback,
  56. MessageBox* message_box)
  57. : title_label_(title_label),
  58. result_callback_(std::move(result_callback)),
  59. message_box_(message_box),
  60. message_box_view_(new views::MessageBoxView(message_label)) {
  61. DCHECK(message_box_);
  62. SetButtonLabel(ui::DIALOG_BUTTON_OK, ok_label);
  63. SetButtonLabel(ui::DIALOG_BUTTON_CANCEL, cancel_label);
  64. auto run_callback = [](MessageBox::Core* core, Result result) {
  65. if (core->result_callback_)
  66. std::move(core->result_callback_).Run(result);
  67. };
  68. SetAcceptCallback(base::BindOnce(run_callback, base::Unretained(this), OK));
  69. SetCancelCallback(
  70. base::BindOnce(run_callback, base::Unretained(this), CANCEL));
  71. SetCloseCallback(
  72. base::BindOnce(run_callback, base::Unretained(this), CANCEL));
  73. RegisterDeleteDelegateCallback(base::BindOnce(
  74. [](Core* dialog) {
  75. if (dialog->message_box_)
  76. dialog->message_box_->core_ = nullptr;
  77. },
  78. this));
  79. }
  80. void MessageBox::Core::Show() {
  81. // The widget is owned by the NativeWidget. See comments in widget.h.
  82. views::Widget* widget =
  83. CreateDialogWidget(this, /* delegate */
  84. nullptr /* parent window*/, nullptr /* parent view */);
  85. if (widget) {
  86. widget->Show();
  87. }
  88. }
  89. void MessageBox::Core::Hide() {
  90. if (GetWidget()) {
  91. GetWidget()->Close();
  92. }
  93. }
  94. ui::ModalType MessageBox::Core::GetModalType() const {
  95. return ui::MODAL_TYPE_SYSTEM;
  96. }
  97. std::u16string MessageBox::Core::GetWindowTitle() const {
  98. return title_label_;
  99. }
  100. views::View* MessageBox::Core::GetContentsView() {
  101. return message_box_view_;
  102. }
  103. views::Widget* MessageBox::Core::GetWidget() {
  104. return message_box_view_->GetWidget();
  105. }
  106. const views::Widget* MessageBox::Core::GetWidget() const {
  107. return message_box_view_->GetWidget();
  108. }
  109. void MessageBox::Core::OnMessageBoxDestroyed() {
  110. DCHECK(message_box_);
  111. message_box_ = nullptr;
  112. // The callback should not be invoked after MessageBox is destroyed.
  113. result_callback_.Reset();
  114. }
  115. BEGIN_METADATA(MessageBox, Core, views::DialogDelegateView)
  116. END_METADATA
  117. MessageBox::MessageBox(const std::u16string& title_label,
  118. const std::u16string& message_label,
  119. const std::u16string& ok_label,
  120. const std::u16string& cancel_label,
  121. ResultCallback result_callback)
  122. : core_(new Core(title_label,
  123. message_label,
  124. ok_label,
  125. cancel_label,
  126. std::move(result_callback),
  127. this)) {}
  128. void MessageBox::Show() {
  129. core_->Show();
  130. }
  131. MessageBox::~MessageBox() {
  132. DCHECK(thread_checker_.CalledOnValidThread());
  133. if (core_) {
  134. core_->OnMessageBoxDestroyed();
  135. core_->Hide();
  136. core_ = nullptr;
  137. }
  138. }
  139. } // namespace remoting