app_modal_dialog_controller.cc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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. #include "components/javascript_dialogs/app_modal_dialog_controller.h"
  5. #include <utility>
  6. #include "build/build_config.h"
  7. #include "components/javascript_dialogs/app_modal_dialog_manager.h"
  8. #include "components/javascript_dialogs/app_modal_dialog_queue.h"
  9. #include "components/javascript_dialogs/app_modal_dialog_view.h"
  10. #include "ui/gfx/text_elider.h"
  11. namespace javascript_dialogs {
  12. namespace {
  13. AppModalDialogObserver* app_modal_dialog_observer = nullptr;
  14. // Control maximum sizes of various texts passed to us from javascript.
  15. #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)
  16. // Two-dimensional eliding. Reformat the text of the message dialog
  17. // inserting line breaks because otherwise a single long line can overflow
  18. // the message dialog (and crash/hang the GTK, depending on the version).
  19. const int kMessageTextMaxRows = 32;
  20. const int kMessageTextMaxCols = 132;
  21. const int kDefaultPromptMaxRows = 24;
  22. const int kDefaultPromptMaxCols = 132;
  23. std::u16string EnforceMaxTextSize(const std::u16string& in_string) {
  24. std::u16string out_string;
  25. gfx::ElideRectangleString(in_string, kMessageTextMaxRows, kMessageTextMaxCols,
  26. false, &out_string);
  27. return out_string;
  28. }
  29. std::u16string EnforceMaxPromptSize(const std::u16string& in_string) {
  30. std::u16string out_string;
  31. gfx::ElideRectangleString(in_string, kDefaultPromptMaxRows,
  32. kDefaultPromptMaxCols, false, &out_string);
  33. return out_string;
  34. }
  35. #else
  36. // One-dimensional eliding. Trust the window system to break the string
  37. // appropriately, but limit its overall length to something reasonable.
  38. const size_t kMessageTextMaxSize = 2000;
  39. const size_t kDefaultPromptMaxSize = 2000;
  40. std::u16string EnforceMaxTextSize(const std::u16string& in_string) {
  41. std::u16string out_string;
  42. gfx::ElideString(in_string, kMessageTextMaxSize, &out_string);
  43. return out_string;
  44. }
  45. std::u16string EnforceMaxPromptSize(const std::u16string& in_string) {
  46. std::u16string out_string;
  47. gfx::ElideString(in_string, kDefaultPromptMaxSize, &out_string);
  48. return out_string;
  49. }
  50. #endif
  51. } // namespace
  52. ChromeJavaScriptDialogExtraData::ChromeJavaScriptDialogExtraData()
  53. : has_already_shown_a_dialog_(false),
  54. suppress_javascript_messages_(false) {}
  55. AppModalDialogController::AppModalDialogController(
  56. content::WebContents* web_contents,
  57. ExtraDataMap* extra_data_map,
  58. const std::u16string& title,
  59. content::JavaScriptDialogType javascript_dialog_type,
  60. const std::u16string& message_text,
  61. const std::u16string& default_prompt_text,
  62. bool display_suppress_checkbox,
  63. bool is_before_unload_dialog,
  64. bool is_reload,
  65. content::JavaScriptDialogManager::DialogClosedCallback callback)
  66. : title_(title),
  67. valid_(true),
  68. view_(nullptr),
  69. web_contents_(web_contents),
  70. extra_data_map_(extra_data_map),
  71. javascript_dialog_type_(javascript_dialog_type),
  72. message_text_(EnforceMaxTextSize(message_text)),
  73. default_prompt_text_(EnforceMaxPromptSize(default_prompt_text)),
  74. display_suppress_checkbox_(display_suppress_checkbox),
  75. is_before_unload_dialog_(is_before_unload_dialog),
  76. is_reload_(is_reload),
  77. callback_(std::move(callback)),
  78. use_override_prompt_text_(false) {}
  79. AppModalDialogController::~AppModalDialogController() {
  80. CompleteDialog();
  81. }
  82. void AppModalDialogController::ShowModalDialog() {
  83. view_ = AppModalDialogManager::GetInstance()->view_factory()->Run(this);
  84. view_->ShowAppModalDialog();
  85. if (app_modal_dialog_observer)
  86. app_modal_dialog_observer->Notify(this);
  87. }
  88. void AppModalDialogController::ActivateModalDialog() {
  89. DCHECK(view_);
  90. view_->ActivateAppModalDialog();
  91. }
  92. void AppModalDialogController::CloseModalDialog() {
  93. DCHECK(view_);
  94. view_->CloseAppModalDialog();
  95. }
  96. void AppModalDialogController::CompleteDialog() {
  97. // If |view_| is non-null, then |this| is the active dialog and the next one
  98. // should be shown. Otherwise, |this| was never shown.
  99. if (view_) {
  100. view_ = nullptr;
  101. AppModalDialogQueue::GetInstance()->ShowNextDialog();
  102. } else {
  103. DCHECK(!valid_);
  104. }
  105. }
  106. bool AppModalDialogController::IsValid() {
  107. return valid_;
  108. }
  109. void AppModalDialogController::Invalidate() {
  110. if (!valid_)
  111. return;
  112. valid_ = false;
  113. CallDialogClosedCallback(false, std::u16string());
  114. if (view_)
  115. CloseModalDialog();
  116. }
  117. void AppModalDialogController::OnCancel(bool suppress_js_messages) {
  118. // We need to do this before WM_DESTROY (WindowClosing()) as any parent frame
  119. // will receive its activation messages before this dialog receives
  120. // WM_DESTROY. The parent frame would then try to activate any modal dialogs
  121. // that were still open in the ModalDialogQueue, which would send activation
  122. // back to this one. The framework should be improved to handle this, so this
  123. // is a temporary workaround.
  124. CompleteDialog();
  125. NotifyDelegate(false, std::u16string(), suppress_js_messages);
  126. }
  127. void AppModalDialogController::OnAccept(const std::u16string& prompt_text,
  128. bool suppress_js_messages) {
  129. std::u16string prompt_text_to_use = prompt_text;
  130. // This is only for testing.
  131. if (use_override_prompt_text_)
  132. prompt_text_to_use = override_prompt_text_;
  133. CompleteDialog();
  134. NotifyDelegate(true, prompt_text_to_use, suppress_js_messages);
  135. }
  136. void AppModalDialogController::OnClose() {
  137. NotifyDelegate(false, std::u16string(), false);
  138. }
  139. void AppModalDialogController::SetOverridePromptText(
  140. const std::u16string& override_prompt_text) {
  141. override_prompt_text_ = override_prompt_text;
  142. use_override_prompt_text_ = true;
  143. }
  144. void AppModalDialogController::NotifyDelegate(bool success,
  145. const std::u16string& user_input,
  146. bool suppress_js_messages) {
  147. if (!valid_)
  148. return;
  149. CallDialogClosedCallback(success, user_input);
  150. // The close callback above may delete web_contents_, thus removing the extra
  151. // data from the map owned by ::AppModalDialogManager. Make sure
  152. // to only use the data if still present. http://crbug.com/236476
  153. auto extra_data = extra_data_map_->find(web_contents_);
  154. if (extra_data != extra_data_map_->end()) {
  155. extra_data->second.has_already_shown_a_dialog_ = true;
  156. extra_data->second.suppress_javascript_messages_ = suppress_js_messages;
  157. }
  158. // On Views, we can end up coming through this code path twice :(.
  159. // See crbug.com/63732.
  160. valid_ = false;
  161. }
  162. void AppModalDialogController::CallDialogClosedCallback(
  163. bool success,
  164. const std::u16string& user_input) {
  165. if (!callback_.is_null())
  166. std::move(callback_).Run(success, user_input);
  167. }
  168. AppModalDialogObserver::AppModalDialogObserver() {
  169. DCHECK(!app_modal_dialog_observer);
  170. app_modal_dialog_observer = this;
  171. }
  172. AppModalDialogObserver::~AppModalDialogObserver() {
  173. DCHECK(app_modal_dialog_observer);
  174. app_modal_dialog_observer = nullptr;
  175. }
  176. } // namespace javascript_dialogs