blob: 54207e1e2233d8e599693668b717c5f330e47837 [file] [log] [blame]
Avi Drissman8ba1bad2022-09-13 19:22:361// Copyright 2012 The Chromium Authors
[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.
Xiaohan Wangbca91f92022-01-15 19:56:2121#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_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,
Morten Stenshorne29ee8052021-08-12 11:06:3477 bool is_before_unload_dialog,
78 bool is_reload,
Avi Drissmane04d3992017-10-05 15:11:3679 content::JavaScriptDialogManager::DialogClosedCallback callback)
Dave Tapuska3b48e9d2024-12-03 19:12:5780 : content::WebContentsObserver(web_contents),
81 title_(title),
[email protected]1f422a7c2013-05-15 17:06:4182 extra_data_map_(extra_data_map),
avi777ff452017-02-09 19:04:4883 javascript_dialog_type_(javascript_dialog_type),
Elly Fong-Jones7337f0cf2019-12-05 21:51:4284 message_text_(EnforceMaxTextSize(message_text)),
85 default_prompt_text_(EnforceMaxPromptSize(default_prompt_text)),
[email protected]12f74a92010-02-05 22:32:1486 display_suppress_checkbox_(display_suppress_checkbox),
Morten Stenshorne29ee8052021-08-12 11:06:3487 is_before_unload_dialog_(is_before_unload_dialog),
88 is_reload_(is_reload),
Avi Drissmane04d3992017-10-05 15:11:3689 callback_(std::move(callback)),
Elly Fong-Jones7337f0cf2019-12-05 21:51:4290 use_override_prompt_text_(false) {}
[email protected]12f74a92010-02-05 22:32:1491
Evan Stade7220e472020-01-31 17:06:5792AppModalDialogController::~AppModalDialogController() {
avi373e72a2017-05-26 20:33:5293 CompleteDialog();
[email protected]12f74a92010-02-05 22:32:1494}
95
Evan Stade7220e472020-01-31 17:06:5796void AppModalDialogController::ShowModalDialog() {
97 view_ = AppModalDialogManager::GetInstance()->view_factory()->Run(this);
98 view_->ShowAppModalDialog();
avi373e72a2017-05-26 20:33:5299 if (app_modal_dialog_observer)
100 app_modal_dialog_observer->Notify(this);
[email protected]160ad3d2010-09-28 15:40:20101}
102
Evan Stade7220e472020-01-31 17:06:57103void AppModalDialogController::ActivateModalDialog() {
104 DCHECK(view_);
105 view_->ActivateAppModalDialog();
avi373e72a2017-05-26 20:33:52106}
107
Evan Stade7220e472020-01-31 17:06:57108void AppModalDialogController::CloseModalDialog() {
109 DCHECK(view_);
110 view_->CloseAppModalDialog();
avi373e72a2017-05-26 20:33:52111}
112
Evan Stade7220e472020-01-31 17:06:57113void AppModalDialogController::CompleteDialog() {
Evan Stade44d63172020-07-16 23:01:44114 // If |view_| is non-null, then |this| is the active dialog and the next one
115 // should be shown. Otherwise, |this| was never shown.
116 if (view_) {
117 view_ = nullptr;
avi373e72a2017-05-26 20:33:52118 AppModalDialogQueue::GetInstance()->ShowNextDialog();
Evan Stade44d63172020-07-16 23:01:44119 } else {
120 DCHECK(!valid_);
avi373e72a2017-05-26 20:33:52121 }
122}
123
Evan Stade7220e472020-01-31 17:06:57124bool AppModalDialogController::IsValid() {
avi373e72a2017-05-26 20:33:52125 return valid_;
[email protected]16623742011-05-16 20:04:26126}
127
Evan Stade7220e472020-01-31 17:06:57128void AppModalDialogController::Invalidate() {
avi373e72a2017-05-26 20:33:52129 if (!valid_)
[email protected]12f74a92010-02-05 22:32:14130 return;
131
avi373e72a2017-05-26 20:33:52132 valid_ = false;
Jan Wilken Dörriefa241ba2021-03-11 17:57:01133 CallDialogClosedCallback(false, std::u16string());
Evan Stade7220e472020-01-31 17:06:57134 if (view_)
[email protected]66711f6f2010-06-23 01:17:35135 CloseModalDialog();
[email protected]12f74a92010-02-05 22:32:14136}
137
Evan Stade7220e472020-01-31 17:06:57138void AppModalDialogController::OnCancel(bool suppress_js_messages) {
[email protected]12f74a92010-02-05 22:32:14139 // We need to do this before WM_DESTROY (WindowClosing()) as any parent frame
140 // will receive its activation messages before this dialog receives
141 // WM_DESTROY. The parent frame would then try to activate any modal dialogs
142 // that were still open in the ModalDialogQueue, which would send activation
143 // back to this one. The framework should be improved to handle this, so this
144 // is a temporary workaround.
145 CompleteDialog();
146
Jan Wilken Dörriefa241ba2021-03-11 17:57:01147 NotifyDelegate(false, std::u16string(), suppress_js_messages);
[email protected]12f74a92010-02-05 22:32:14148}
149
Jan Wilken Dörriefa241ba2021-03-11 17:57:01150void AppModalDialogController::OnAccept(const std::u16string& prompt_text,
[email protected]12f74a92010-02-05 22:32:14151 bool suppress_js_messages) {
Jan Wilken Dörriefa241ba2021-03-11 17:57:01152 std::u16string prompt_text_to_use = prompt_text;
[email protected]16623742011-05-16 20:04:26153 // This is only for testing.
154 if (use_override_prompt_text_)
[email protected]3ab9cb82011-06-03 18:02:07155 prompt_text_to_use = override_prompt_text_;
[email protected]16623742011-05-16 20:04:26156
[email protected]12f74a92010-02-05 22:32:14157 CompleteDialog();
[email protected]16623742011-05-16 20:04:26158 NotifyDelegate(true, prompt_text_to_use, suppress_js_messages);
[email protected]12f74a92010-02-05 22:32:14159}
[email protected]7d784302010-04-09 21:41:05160
Evan Stade7220e472020-01-31 17:06:57161void AppModalDialogController::OnClose() {
Jan Wilken Dörriefa241ba2021-03-11 17:57:01162 NotifyDelegate(false, std::u16string(), false);
[email protected]7d784302010-04-09 21:41:05163}
164
Evan Stade7220e472020-01-31 17:06:57165void AppModalDialogController::SetOverridePromptText(
Jan Wilken Dörriefa241ba2021-03-11 17:57:01166 const std::u16string& override_prompt_text) {
[email protected]16623742011-05-16 20:04:26167 override_prompt_text_ = override_prompt_text;
168 use_override_prompt_text_ = true;
169}
170
Dave Tapuska3b48e9d2024-12-03 19:12:57171void AppModalDialogController::WebContentsDestroyed() {
172 Invalidate();
173}
174
Evan Stade7220e472020-01-31 17:06:57175void AppModalDialogController::NotifyDelegate(bool success,
Jan Wilken Dörriefa241ba2021-03-11 17:57:01176 const std::u16string& user_input,
[email protected]594d0622010-12-07 05:33:07177 bool suppress_js_messages) {
avi373e72a2017-05-26 20:33:52178 if (!valid_)
[email protected]594d0622010-12-07 05:33:07179 return;
180
joenotcharles850904a2016-02-09 01:50:44181 CallDialogClosedCallback(success, user_input);
[email protected]3ab9cb82011-06-03 18:02:07182
joenotcharles850904a2016-02-09 01:50:44183 // The close callback above may delete web_contents_, thus removing the extra
Evan Stade7220e472020-01-31 17:06:57184 // data from the map owned by ::AppModalDialogManager. Make sure
[email protected]1f422a7c2013-05-15 17:06:41185 // to only use the data if still present. http://crbug.com/236476
Dave Tapuska3b48e9d2024-12-03 19:12:57186 if (auto* contents = web_contents()) {
187 auto extra_data = extra_data_map_->find(contents);
188 if (extra_data != extra_data_map_->end()) {
189 extra_data->second.has_already_shown_a_dialog_ = true;
190 extra_data->second.suppress_javascript_messages_ = suppress_js_messages;
191 }
[email protected]1f422a7c2013-05-15 17:06:41192 }
[email protected]594d0622010-12-07 05:33:07193
194 // On Views, we can end up coming through this code path twice :(.
195 // See crbug.com/63732.
avi373e72a2017-05-26 20:33:52196 valid_ = false;
[email protected]7d784302010-04-09 21:41:05197}
oshima0929be2a2014-11-19 22:21:03198
Evan Stade7220e472020-01-31 17:06:57199void AppModalDialogController::CallDialogClosedCallback(
200 bool success,
Jan Wilken Dörriefa241ba2021-03-11 17:57:01201 const std::u16string& user_input) {
Avi Drissmane04d3992017-10-05 15:11:36202 if (!callback_.is_null())
203 std::move(callback_).Run(success, user_input);
joenotcharles850904a2016-02-09 01:50:44204}
205
avi373e72a2017-05-26 20:33:52206AppModalDialogObserver::AppModalDialogObserver() {
207 DCHECK(!app_modal_dialog_observer);
208 app_modal_dialog_observer = this;
209}
210
211AppModalDialogObserver::~AppModalDialogObserver() {
212 DCHECK(app_modal_dialog_observer);
213 app_modal_dialog_observer = nullptr;
214}
215
Evan Stade7220e472020-01-31 17:06:57216} // namespace javascript_dialogs