blob: 75f27d75c820b602d1fae768d62ef0a12b795096 [file] [log] [blame]
[email protected]fedec012012-01-28 03:09:341// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]12f74a92010-02-05 22:32:142// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Evan Stade7220e472020-01-31 17:06:575#include "components/javascript_dialogs/app_modal_dialog_controller.h"
[email protected]12f74a92010-02-05 22:32:146
Avi Drissmane04d3992017-10-05 15:11:367#include <utility>
8
avibc5337b2015-12-25 23:16:339#include "build/build_config.h"
Evan Stade7220e472020-01-31 17:06:5710#include "components/javascript_dialogs/app_modal_dialog_manager.h"
11#include "components/javascript_dialogs/app_modal_dialog_queue.h"
12#include "components/javascript_dialogs/app_modal_dialog_view.h"
[email protected]dbb97ba2013-09-09 22:15:2513#include "ui/gfx/text_elider.h"
[email protected]51da7e32012-01-30 19:24:5214
Evan Stade7220e472020-01-31 17:06:5715namespace javascript_dialogs {
[email protected]999adfd62010-06-02 19:42:4216namespace {
17
avi373e72a2017-05-26 20:33:5218AppModalDialogObserver* app_modal_dialog_observer = nullptr;
19
[email protected]416126c52011-03-29 16:28:5720// Control maximum sizes of various texts passed to us from javascript.
Avi Drissman8fd92172020-07-28 15:49:4521#if defined(OS_POSIX) && !defined(OS_APPLE)
[email protected]416126c52011-03-29 16:28:5722// Two-dimensional eliding. Reformat the text of the message dialog
23// inserting line breaks because otherwise a single long line can overflow
24// the message dialog (and crash/hang the GTK, depending on the version).
[email protected]af4b9df2010-12-22 21:19:0225const int kMessageTextMaxRows = 32;
26const int kMessageTextMaxCols = 132;
[email protected]416126c52011-03-29 16:28:5727const int kDefaultPromptMaxRows = 24;
28const int kDefaultPromptMaxCols = 132;
Elly Fong-Jones7337f0cf2019-12-05 21:51:4229
Jan Wilken Dörriefa241ba2021-03-11 17:57:0130std::u16string EnforceMaxTextSize(const std::u16string& in_string) {
31 std::u16string out_string;
Elly Fong-Jones7337f0cf2019-12-05 21:51:4232 gfx::ElideRectangleString(in_string, kMessageTextMaxRows, kMessageTextMaxCols,
33 false, &out_string);
34 return out_string;
[email protected]416126c52011-03-29 16:28:5735}
Elly Fong-Jones7337f0cf2019-12-05 21:51:4236
Jan Wilken Dörriefa241ba2021-03-11 17:57:0137std::u16string EnforceMaxPromptSize(const std::u16string& in_string) {
38 std::u16string out_string;
[email protected]dbb97ba2013-09-09 22:15:2539 gfx::ElideRectangleString(in_string, kDefaultPromptMaxRows,
Elly Fong-Jones7337f0cf2019-12-05 21:51:4240 kDefaultPromptMaxCols, false, &out_string);
41 return out_string;
[email protected]416126c52011-03-29 16:28:5742}
Elly Fong-Jones7337f0cf2019-12-05 21:51:4243
[email protected]416126c52011-03-29 16:28:5744#else
45// One-dimensional eliding. Trust the window system to break the string
46// appropriately, but limit its overall length to something reasonable.
thestigbbf93ac2016-02-02 00:24:4947const size_t kMessageTextMaxSize = 2000;
48const size_t kDefaultPromptMaxSize = 2000;
Elly Fong-Jones7337f0cf2019-12-05 21:51:4249
Jan Wilken Dörriefa241ba2021-03-11 17:57:0150std::u16string EnforceMaxTextSize(const std::u16string& in_string) {
51 std::u16string out_string;
Elly Fong-Jones7337f0cf2019-12-05 21:51:4252 gfx::ElideString(in_string, kMessageTextMaxSize, &out_string);
53 return out_string;
[email protected]416126c52011-03-29 16:28:5754}
Elly Fong-Jones7337f0cf2019-12-05 21:51:4255
Jan Wilken Dörriefa241ba2021-03-11 17:57:0156std::u16string EnforceMaxPromptSize(const std::u16string& in_string) {
57 std::u16string out_string;
Elly Fong-Jones7337f0cf2019-12-05 21:51:4258 gfx::ElideString(in_string, kDefaultPromptMaxSize, &out_string);
59 return out_string;
[email protected]416126c52011-03-29 16:28:5760}
61#endif
[email protected]999adfd62010-06-02 19:42:4262
63} // namespace
64
[email protected]3ab9cb82011-06-03 18:02:0765ChromeJavaScriptDialogExtraData::ChromeJavaScriptDialogExtraData()
palmerd8b2ff02015-08-18 00:24:5966 : has_already_shown_a_dialog_(false),
Joe Masondb32d7f02019-07-19 00:14:2267 suppress_javascript_messages_(false) {}
[email protected]3ab9cb82011-06-03 18:02:0768
Evan Stade7220e472020-01-31 17:06:5769AppModalDialogController::AppModalDialogController(
jochena2afdec2015-01-23 13:09:2270 content::WebContents* web_contents,
[email protected]1f422a7c2013-05-15 17:06:4171 ExtraDataMap* extra_data_map,
Jan Wilken Dörriefa241ba2021-03-11 17:57:0172 const std::u16string& title,
avi777ff452017-02-09 19:04:4873 content::JavaScriptDialogType javascript_dialog_type,
Jan Wilken Dörriefa241ba2021-03-11 17:57:0174 const std::u16string& message_text,
75 const std::u16string& default_prompt_text,
[email protected]12f74a92010-02-05 22:32:1476 bool display_suppress_checkbox,
77 bool is_before_unload_dialog,
[email protected]3b3301f62012-02-29 04:32:3278 bool is_reload,
Avi Drissmane04d3992017-10-05 15:11:3679 content::JavaScriptDialogManager::DialogClosedCallback callback)
avi373e72a2017-05-26 20:33:5280 : title_(title),
avi373e72a2017-05-26 20:33:5281 valid_(true),
Evan Stade7220e472020-01-31 17:06:5782 view_(nullptr),
avi373e72a2017-05-26 20:33:5283 web_contents_(web_contents),
[email protected]1f422a7c2013-05-15 17:06:4184 extra_data_map_(extra_data_map),
avi777ff452017-02-09 19:04:4885 javascript_dialog_type_(javascript_dialog_type),
Elly Fong-Jones7337f0cf2019-12-05 21:51:4286 message_text_(EnforceMaxTextSize(message_text)),
87 default_prompt_text_(EnforceMaxPromptSize(default_prompt_text)),
[email protected]12f74a92010-02-05 22:32:1488 display_suppress_checkbox_(display_suppress_checkbox),
89 is_before_unload_dialog_(is_before_unload_dialog),
[email protected]3b3301f62012-02-29 04:32:3290 is_reload_(is_reload),
Avi Drissmane04d3992017-10-05 15:11:3691 callback_(std::move(callback)),
Elly Fong-Jones7337f0cf2019-12-05 21:51:4292 use_override_prompt_text_(false) {}
[email protected]12f74a92010-02-05 22:32:1493
Evan Stade7220e472020-01-31 17:06:5794AppModalDialogController::~AppModalDialogController() {
avi373e72a2017-05-26 20:33:5295 CompleteDialog();
[email protected]12f74a92010-02-05 22:32:1496}
97
Evan Stade7220e472020-01-31 17:06:5798void AppModalDialogController::ShowModalDialog() {
99 view_ = AppModalDialogManager::GetInstance()->view_factory()->Run(this);
100 view_->ShowAppModalDialog();
avi373e72a2017-05-26 20:33:52101 if (app_modal_dialog_observer)
102 app_modal_dialog_observer->Notify(this);
[email protected]160ad3d2010-09-28 15:40:20103}
104
Evan Stade7220e472020-01-31 17:06:57105void AppModalDialogController::ActivateModalDialog() {
106 DCHECK(view_);
107 view_->ActivateAppModalDialog();
avi373e72a2017-05-26 20:33:52108}
109
Evan Stade7220e472020-01-31 17:06:57110void AppModalDialogController::CloseModalDialog() {
111 DCHECK(view_);
112 view_->CloseAppModalDialog();
avi373e72a2017-05-26 20:33:52113}
114
Evan Stade7220e472020-01-31 17:06:57115void AppModalDialogController::CompleteDialog() {
Evan Stade44d63172020-07-16 23:01:44116 // If |view_| is non-null, then |this| is the active dialog and the next one
117 // should be shown. Otherwise, |this| was never shown.
118 if (view_) {
119 view_ = nullptr;
avi373e72a2017-05-26 20:33:52120 AppModalDialogQueue::GetInstance()->ShowNextDialog();
Evan Stade44d63172020-07-16 23:01:44121 } else {
122 DCHECK(!valid_);
avi373e72a2017-05-26 20:33:52123 }
124}
125
Evan Stade7220e472020-01-31 17:06:57126bool AppModalDialogController::IsValid() {
avi373e72a2017-05-26 20:33:52127 return valid_;
[email protected]16623742011-05-16 20:04:26128}
129
Evan Stade7220e472020-01-31 17:06:57130void AppModalDialogController::Invalidate() {
avi373e72a2017-05-26 20:33:52131 if (!valid_)
[email protected]12f74a92010-02-05 22:32:14132 return;
133
avi373e72a2017-05-26 20:33:52134 valid_ = false;
Jan Wilken Dörriefa241ba2021-03-11 17:57:01135 CallDialogClosedCallback(false, std::u16string());
Evan Stade7220e472020-01-31 17:06:57136 if (view_)
[email protected]66711f6f2010-06-23 01:17:35137 CloseModalDialog();
[email protected]12f74a92010-02-05 22:32:14138}
139
Evan Stade7220e472020-01-31 17:06:57140void AppModalDialogController::OnCancel(bool suppress_js_messages) {
[email protected]12f74a92010-02-05 22:32:14141 // We need to do this before WM_DESTROY (WindowClosing()) as any parent frame
142 // will receive its activation messages before this dialog receives
143 // WM_DESTROY. The parent frame would then try to activate any modal dialogs
144 // that were still open in the ModalDialogQueue, which would send activation
145 // back to this one. The framework should be improved to handle this, so this
146 // is a temporary workaround.
147 CompleteDialog();
148
Jan Wilken Dörriefa241ba2021-03-11 17:57:01149 NotifyDelegate(false, std::u16string(), suppress_js_messages);
[email protected]12f74a92010-02-05 22:32:14150}
151
Jan Wilken Dörriefa241ba2021-03-11 17:57:01152void AppModalDialogController::OnAccept(const std::u16string& prompt_text,
[email protected]12f74a92010-02-05 22:32:14153 bool suppress_js_messages) {
Jan Wilken Dörriefa241ba2021-03-11 17:57:01154 std::u16string prompt_text_to_use = prompt_text;
[email protected]16623742011-05-16 20:04:26155 // This is only for testing.
156 if (use_override_prompt_text_)
[email protected]3ab9cb82011-06-03 18:02:07157 prompt_text_to_use = override_prompt_text_;
[email protected]16623742011-05-16 20:04:26158
[email protected]12f74a92010-02-05 22:32:14159 CompleteDialog();
[email protected]16623742011-05-16 20:04:26160 NotifyDelegate(true, prompt_text_to_use, suppress_js_messages);
[email protected]12f74a92010-02-05 22:32:14161}
[email protected]7d784302010-04-09 21:41:05162
Evan Stade7220e472020-01-31 17:06:57163void AppModalDialogController::OnClose() {
Jan Wilken Dörriefa241ba2021-03-11 17:57:01164 NotifyDelegate(false, std::u16string(), false);
[email protected]7d784302010-04-09 21:41:05165}
166
Evan Stade7220e472020-01-31 17:06:57167void AppModalDialogController::SetOverridePromptText(
Jan Wilken Dörriefa241ba2021-03-11 17:57:01168 const std::u16string& override_prompt_text) {
[email protected]16623742011-05-16 20:04:26169 override_prompt_text_ = override_prompt_text;
170 use_override_prompt_text_ = true;
171}
172
Evan Stade7220e472020-01-31 17:06:57173void AppModalDialogController::NotifyDelegate(bool success,
Jan Wilken Dörriefa241ba2021-03-11 17:57:01174 const std::u16string& user_input,
[email protected]594d0622010-12-07 05:33:07175 bool suppress_js_messages) {
avi373e72a2017-05-26 20:33:52176 if (!valid_)
[email protected]594d0622010-12-07 05:33:07177 return;
178
joenotcharles850904a2016-02-09 01:50:44179 CallDialogClosedCallback(success, user_input);
[email protected]3ab9cb82011-06-03 18:02:07180
joenotcharles850904a2016-02-09 01:50:44181 // The close callback above may delete web_contents_, thus removing the extra
Evan Stade7220e472020-01-31 17:06:57182 // data from the map owned by ::AppModalDialogManager. Make sure
[email protected]1f422a7c2013-05-15 17:06:41183 // to only use the data if still present. http://crbug.com/236476
jdoerrie3feb1852018-10-05 12:16:44184 auto extra_data = extra_data_map_->find(web_contents_);
[email protected]1f422a7c2013-05-15 17:06:41185 if (extra_data != extra_data_map_->end()) {
palmerd8b2ff02015-08-18 00:24:59186 extra_data->second.has_already_shown_a_dialog_ = true;
[email protected]1f422a7c2013-05-15 17:06:41187 extra_data->second.suppress_javascript_messages_ = suppress_js_messages;
188 }
[email protected]594d0622010-12-07 05:33:07189
190 // On Views, we can end up coming through this code path twice :(.
191 // See crbug.com/63732.
avi373e72a2017-05-26 20:33:52192 valid_ = false;
[email protected]7d784302010-04-09 21:41:05193}
oshima0929be2a2014-11-19 22:21:03194
Evan Stade7220e472020-01-31 17:06:57195void AppModalDialogController::CallDialogClosedCallback(
196 bool success,
Jan Wilken Dörriefa241ba2021-03-11 17:57:01197 const std::u16string& user_input) {
Avi Drissmane04d3992017-10-05 15:11:36198 if (!callback_.is_null())
199 std::move(callback_).Run(success, user_input);
joenotcharles850904a2016-02-09 01:50:44200}
201
avi373e72a2017-05-26 20:33:52202AppModalDialogObserver::AppModalDialogObserver() {
203 DCHECK(!app_modal_dialog_observer);
204 app_modal_dialog_observer = this;
205}
206
207AppModalDialogObserver::~AppModalDialogObserver() {
208 DCHECK(app_modal_dialog_observer);
209 app_modal_dialog_observer = nullptr;
210}
211
Evan Stade7220e472020-01-31 17:06:57212} // namespace javascript_dialogs