[email protected] | fedec01 | 2012-01-28 03:09:34 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | 12f74a9 | 2010-02-05 22:32:14 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
oshima | f6539842 | 2014-11-18 23:30:42 | [diff] [blame] | 5 | #include "components/app_modal/javascript_app_modal_dialog.h" |
[email protected] | 12f74a9 | 2010-02-05 22:32:14 | [diff] [blame] | 6 | |
oshima | 0929be2a | 2014-11-19 22:21:03 | [diff] [blame^] | 7 | #include "components/app_modal/javascript_dialog_manager.h" |
oshima | f6539842 | 2014-11-18 23:30:42 | [diff] [blame] | 8 | #include "components/app_modal/javascript_native_dialog_factory.h" |
[email protected] | 51da7e3 | 2012-01-30 19:24:52 | [diff] [blame] | 9 | #include "content/public/browser/web_contents.h" |
[email protected] | dbb97ba | 2013-09-09 22:15:25 | [diff] [blame] | 10 | #include "ui/gfx/text_elider.h" |
[email protected] | 12f74a9 | 2010-02-05 22:32:14 | [diff] [blame] | 11 | |
[email protected] | 2a2caa0 | 2013-01-22 20:50:36 | [diff] [blame] | 12 | #if defined(USE_AURA) |
[email protected] | f7c05b2 | 2013-11-12 21:07:24 | [diff] [blame] | 13 | #include "ui/aura/window.h" |
[email protected] | fcc51c95 | 2014-02-21 21:31:26 | [diff] [blame] | 14 | #include "ui/aura/window_event_dispatcher.h" |
[email protected] | 2a2caa0 | 2013-01-22 20:50:36 | [diff] [blame] | 15 | #endif |
| 16 | |
[email protected] | 51da7e3 | 2012-01-30 19:24:52 | [diff] [blame] | 17 | using content::WebContents; |
| 18 | |
oshima | 0929be2a | 2014-11-19 22:21:03 | [diff] [blame^] | 19 | namespace app_modal { |
[email protected] | 999adfd6 | 2010-06-02 19:42:42 | [diff] [blame] | 20 | namespace { |
| 21 | |
[email protected] | 416126c5 | 2011-03-29 16:28:57 | [diff] [blame] | 22 | // Control maximum sizes of various texts passed to us from javascript. |
[email protected] | 7be6450 | 2011-05-03 17:51:47 | [diff] [blame] | 23 | #if defined(OS_POSIX) && !defined(OS_MACOSX) |
[email protected] | 416126c5 | 2011-03-29 16:28:57 | [diff] [blame] | 24 | // Two-dimensional eliding. Reformat the text of the message dialog |
| 25 | // inserting line breaks because otherwise a single long line can overflow |
| 26 | // the message dialog (and crash/hang the GTK, depending on the version). |
[email protected] | af4b9df | 2010-12-22 21:19:02 | [diff] [blame] | 27 | const int kMessageTextMaxRows = 32; |
| 28 | const int kMessageTextMaxCols = 132; |
[email protected] | 416126c5 | 2011-03-29 16:28:57 | [diff] [blame] | 29 | const int kDefaultPromptMaxRows = 24; |
| 30 | const int kDefaultPromptMaxCols = 132; |
[email protected] | dcd024987 | 2013-12-06 23:58:45 | [diff] [blame] | 31 | void EnforceMaxTextSize(const base::string16& in_string, |
| 32 | base::string16* out_string) { |
[email protected] | dbb97ba | 2013-09-09 22:15:25 | [diff] [blame] | 33 | gfx::ElideRectangleString(in_string, kMessageTextMaxRows, |
[email protected] | 416126c5 | 2011-03-29 16:28:57 | [diff] [blame] | 34 | kMessageTextMaxCols, false, out_string); |
| 35 | } |
[email protected] | dcd024987 | 2013-12-06 23:58:45 | [diff] [blame] | 36 | void EnforceMaxPromptSize(const base::string16& in_string, |
| 37 | base::string16* out_string) { |
[email protected] | dbb97ba | 2013-09-09 22:15:25 | [diff] [blame] | 38 | gfx::ElideRectangleString(in_string, kDefaultPromptMaxRows, |
[email protected] | 416126c5 | 2011-03-29 16:28:57 | [diff] [blame] | 39 | kDefaultPromptMaxCols, false, out_string); |
| 40 | } |
| 41 | #else |
| 42 | // One-dimensional eliding. Trust the window system to break the string |
| 43 | // appropriately, but limit its overall length to something reasonable. |
| 44 | const int kMessageTextMaxSize = 3000; |
| 45 | const int kDefaultPromptMaxSize = 2000; |
[email protected] | dcd024987 | 2013-12-06 23:58:45 | [diff] [blame] | 46 | void EnforceMaxTextSize(const base::string16& in_string, |
| 47 | base::string16* out_string) { |
[email protected] | dbb97ba | 2013-09-09 22:15:25 | [diff] [blame] | 48 | gfx::ElideString(in_string, kMessageTextMaxSize, out_string); |
[email protected] | 416126c5 | 2011-03-29 16:28:57 | [diff] [blame] | 49 | } |
[email protected] | dcd024987 | 2013-12-06 23:58:45 | [diff] [blame] | 50 | void EnforceMaxPromptSize(const base::string16& in_string, |
| 51 | base::string16* out_string) { |
[email protected] | dbb97ba | 2013-09-09 22:15:25 | [diff] [blame] | 52 | gfx::ElideString(in_string, kDefaultPromptMaxSize, out_string); |
[email protected] | 416126c5 | 2011-03-29 16:28:57 | [diff] [blame] | 53 | } |
| 54 | #endif |
[email protected] | 999adfd6 | 2010-06-02 19:42:42 | [diff] [blame] | 55 | |
| 56 | } // namespace |
| 57 | |
[email protected] | 3ab9cb8 | 2011-06-03 18:02:07 | [diff] [blame] | 58 | ChromeJavaScriptDialogExtraData::ChromeJavaScriptDialogExtraData() |
| 59 | : suppress_javascript_messages_(false) { |
| 60 | } |
| 61 | |
[email protected] | 12f74a9 | 2010-02-05 22:32:14 | [diff] [blame] | 62 | JavaScriptAppModalDialog::JavaScriptAppModalDialog( |
[email protected] | 51da7e3 | 2012-01-30 19:24:52 | [diff] [blame] | 63 | WebContents* web_contents, |
[email protected] | 1f422a7c | 2013-05-15 17:06:41 | [diff] [blame] | 64 | ExtraDataMap* extra_data_map, |
[email protected] | dcd024987 | 2013-12-06 23:58:45 | [diff] [blame] | 65 | const base::string16& title, |
[email protected] | be2510c0 | 2012-05-28 14:52:14 | [diff] [blame] | 66 | content::JavaScriptMessageType javascript_message_type, |
[email protected] | dcd024987 | 2013-12-06 23:58:45 | [diff] [blame] | 67 | const base::string16& message_text, |
| 68 | const base::string16& default_prompt_text, |
[email protected] | 12f74a9 | 2010-02-05 22:32:14 | [diff] [blame] | 69 | bool display_suppress_checkbox, |
| 70 | bool is_before_unload_dialog, |
[email protected] | 3b3301f6 | 2012-02-29 04:32:32 | [diff] [blame] | 71 | bool is_reload, |
oshima | 0929be2a | 2014-11-19 22:21:03 | [diff] [blame^] | 72 | const content::JavaScriptDialogManager::DialogClosedCallback& callback) |
[email protected] | 51da7e3 | 2012-01-30 19:24:52 | [diff] [blame] | 73 | : AppModalDialog(web_contents, title), |
[email protected] | 1f422a7c | 2013-05-15 17:06:41 | [diff] [blame] | 74 | extra_data_map_(extra_data_map), |
[email protected] | 269f86d | 2011-12-07 02:43:47 | [diff] [blame] | 75 | javascript_message_type_(javascript_message_type), |
[email protected] | 12f74a9 | 2010-02-05 22:32:14 | [diff] [blame] | 76 | display_suppress_checkbox_(display_suppress_checkbox), |
| 77 | is_before_unload_dialog_(is_before_unload_dialog), |
[email protected] | 3b3301f6 | 2012-02-29 04:32:32 | [diff] [blame] | 78 | is_reload_(is_reload), |
[email protected] | 51da7e3 | 2012-01-30 19:24:52 | [diff] [blame] | 79 | callback_(callback), |
[email protected] | 1662374 | 2011-05-16 20:04:26 | [diff] [blame] | 80 | use_override_prompt_text_(false) { |
[email protected] | 3ab9cb8 | 2011-06-03 18:02:07 | [diff] [blame] | 81 | EnforceMaxTextSize(message_text, &message_text_); |
| 82 | EnforceMaxPromptSize(default_prompt_text, &default_prompt_text_); |
[email protected] | 12f74a9 | 2010-02-05 22:32:14 | [diff] [blame] | 83 | } |
| 84 | |
| 85 | JavaScriptAppModalDialog::~JavaScriptAppModalDialog() { |
| 86 | } |
| 87 | |
[email protected] | 160ad3d | 2010-09-28 15:40:20 | [diff] [blame] | 88 | NativeAppModalDialog* JavaScriptAppModalDialog::CreateNativeDialog() { |
[email protected] | fc2b46b | 2014-05-03 16:33:45 | [diff] [blame] | 89 | gfx::NativeWindow parent_window = web_contents()->GetTopLevelNativeWindow(); |
[email protected] | 884401d3 | 2013-05-02 18:53:37 | [diff] [blame] | 90 | |
[email protected] | 2a2caa0 | 2013-01-22 20:50:36 | [diff] [blame] | 91 | #if defined(USE_AURA) |
| 92 | if (!parent_window->GetRootWindow()) { |
| 93 | // When we are part of a WebContents that isn't actually being displayed on |
| 94 | // the screen, we can't actually attach to it. |
| 95 | parent_window = NULL; |
| 96 | } |
[email protected] | 884401d3 | 2013-05-02 18:53:37 | [diff] [blame] | 97 | #endif // defined(USE_AURA) |
oshima | 0929be2a | 2014-11-19 22:21:03 | [diff] [blame^] | 98 | return JavaScriptDialogManager::GetInstance()->native_dialog_factory()-> |
oshima | 758abebc | 2014-11-06 10:55:50 | [diff] [blame] | 99 | CreateNativeJavaScriptDialog(this, parent_window); |
[email protected] | 160ad3d | 2010-09-28 15:40:20 | [diff] [blame] | 100 | } |
| 101 | |
[email protected] | 1662374 | 2011-05-16 20:04:26 | [diff] [blame] | 102 | bool JavaScriptAppModalDialog::IsJavaScriptModalDialog() { |
| 103 | return true; |
| 104 | } |
| 105 | |
[email protected] | a1e97f0 | 2011-06-30 14:04:34 | [diff] [blame] | 106 | void JavaScriptAppModalDialog::Invalidate() { |
[email protected] | 1f422a7c | 2013-05-15 17:06:41 | [diff] [blame] | 107 | if (!IsValid()) |
[email protected] | 12f74a9 | 2010-02-05 22:32:14 | [diff] [blame] | 108 | return; |
| 109 | |
[email protected] | 1f422a7c | 2013-05-15 17:06:41 | [diff] [blame] | 110 | AppModalDialog::Invalidate(); |
[email protected] | af90590 | 2013-10-01 21:38:51 | [diff] [blame] | 111 | if (!callback_.is_null()) { |
[email protected] | dcd024987 | 2013-12-06 23:58:45 | [diff] [blame] | 112 | callback_.Run(false, base::string16()); |
[email protected] | af90590 | 2013-10-01 21:38:51 | [diff] [blame] | 113 | callback_.Reset(); |
| 114 | } |
[email protected] | 1f422a7c | 2013-05-15 17:06:41 | [diff] [blame] | 115 | if (native_dialog()) |
[email protected] | 66711f6f | 2010-06-23 01:17:35 | [diff] [blame] | 116 | CloseModalDialog(); |
[email protected] | 12f74a9 | 2010-02-05 22:32:14 | [diff] [blame] | 117 | } |
| 118 | |
[email protected] | ab96d31 | 2010-10-14 13:38:51 | [diff] [blame] | 119 | void JavaScriptAppModalDialog::OnCancel(bool suppress_js_messages) { |
[email protected] | 12f74a9 | 2010-02-05 22:32:14 | [diff] [blame] | 120 | // We need to do this before WM_DESTROY (WindowClosing()) as any parent frame |
| 121 | // will receive its activation messages before this dialog receives |
| 122 | // WM_DESTROY. The parent frame would then try to activate any modal dialogs |
| 123 | // that were still open in the ModalDialogQueue, which would send activation |
| 124 | // back to this one. The framework should be improved to handle this, so this |
| 125 | // is a temporary workaround. |
| 126 | CompleteDialog(); |
| 127 | |
[email protected] | dcd024987 | 2013-12-06 23:58:45 | [diff] [blame] | 128 | NotifyDelegate(false, base::string16(), suppress_js_messages); |
[email protected] | 12f74a9 | 2010-02-05 22:32:14 | [diff] [blame] | 129 | } |
| 130 | |
[email protected] | dcd024987 | 2013-12-06 23:58:45 | [diff] [blame] | 131 | void JavaScriptAppModalDialog::OnAccept(const base::string16& prompt_text, |
[email protected] | 12f74a9 | 2010-02-05 22:32:14 | [diff] [blame] | 132 | bool suppress_js_messages) { |
[email protected] | dcd024987 | 2013-12-06 23:58:45 | [diff] [blame] | 133 | base::string16 prompt_text_to_use = prompt_text; |
[email protected] | 1662374 | 2011-05-16 20:04:26 | [diff] [blame] | 134 | // This is only for testing. |
| 135 | if (use_override_prompt_text_) |
[email protected] | 3ab9cb8 | 2011-06-03 18:02:07 | [diff] [blame] | 136 | prompt_text_to_use = override_prompt_text_; |
[email protected] | 1662374 | 2011-05-16 20:04:26 | [diff] [blame] | 137 | |
[email protected] | 12f74a9 | 2010-02-05 22:32:14 | [diff] [blame] | 138 | CompleteDialog(); |
[email protected] | 1662374 | 2011-05-16 20:04:26 | [diff] [blame] | 139 | NotifyDelegate(true, prompt_text_to_use, suppress_js_messages); |
[email protected] | 12f74a9 | 2010-02-05 22:32:14 | [diff] [blame] | 140 | } |
[email protected] | 7d78430 | 2010-04-09 21:41:05 | [diff] [blame] | 141 | |
| 142 | void JavaScriptAppModalDialog::OnClose() { |
[email protected] | dcd024987 | 2013-12-06 23:58:45 | [diff] [blame] | 143 | NotifyDelegate(false, base::string16(), false); |
[email protected] | 7d78430 | 2010-04-09 21:41:05 | [diff] [blame] | 144 | } |
| 145 | |
[email protected] | 1662374 | 2011-05-16 20:04:26 | [diff] [blame] | 146 | void JavaScriptAppModalDialog::SetOverridePromptText( |
[email protected] | dcd024987 | 2013-12-06 23:58:45 | [diff] [blame] | 147 | const base::string16& override_prompt_text) { |
[email protected] | 1662374 | 2011-05-16 20:04:26 | [diff] [blame] | 148 | override_prompt_text_ = override_prompt_text; |
| 149 | use_override_prompt_text_ = true; |
| 150 | } |
| 151 | |
[email protected] | 594d062 | 2010-12-07 05:33:07 | [diff] [blame] | 152 | void JavaScriptAppModalDialog::NotifyDelegate(bool success, |
[email protected] | dcd024987 | 2013-12-06 23:58:45 | [diff] [blame] | 153 | const base::string16& user_input, |
[email protected] | 594d062 | 2010-12-07 05:33:07 | [diff] [blame] | 154 | bool suppress_js_messages) { |
[email protected] | 1f422a7c | 2013-05-15 17:06:41 | [diff] [blame] | 155 | if (!IsValid()) |
[email protected] | 594d062 | 2010-12-07 05:33:07 | [diff] [blame] | 156 | return; |
| 157 | |
[email protected] | af90590 | 2013-10-01 21:38:51 | [diff] [blame] | 158 | if (!callback_.is_null()) { |
| 159 | callback_.Run(success, user_input); |
| 160 | callback_.Reset(); |
| 161 | } |
[email protected] | 3ab9cb8 | 2011-06-03 18:02:07 | [diff] [blame] | 162 | |
[email protected] | 1f422a7c | 2013-05-15 17:06:41 | [diff] [blame] | 163 | // The callback_ above may delete web_contents_, thus removing the extra |
oshima | 0929be2a | 2014-11-19 22:21:03 | [diff] [blame^] | 164 | // data from the map owned by ::JavaScriptDialogManager. Make sure |
[email protected] | 1f422a7c | 2013-05-15 17:06:41 | [diff] [blame] | 165 | // to only use the data if still present. http://crbug.com/236476 |
| 166 | ExtraDataMap::iterator extra_data = extra_data_map_->find(web_contents()); |
| 167 | if (extra_data != extra_data_map_->end()) { |
| 168 | extra_data->second.last_javascript_message_dismissal_ = |
| 169 | base::TimeTicks::Now(); |
| 170 | extra_data->second.suppress_javascript_messages_ = suppress_js_messages; |
| 171 | } |
[email protected] | 594d062 | 2010-12-07 05:33:07 | [diff] [blame] | 172 | |
| 173 | // On Views, we can end up coming through this code path twice :(. |
| 174 | // See crbug.com/63732. |
[email protected] | 1f422a7c | 2013-05-15 17:06:41 | [diff] [blame] | 175 | AppModalDialog::Invalidate(); |
[email protected] | 7d78430 | 2010-04-09 21:41:05 | [diff] [blame] | 176 | } |
oshima | 0929be2a | 2014-11-19 22:21:03 | [diff] [blame^] | 177 | |
| 178 | } // namespace app_modal |