Don't close dialogs in response to cancel event
A *trusted* cancel event can close dialog elements. This is hooked up to
the default keyboard event handler, which fires a trusted cancel event,
in order to make the escape key close dialog elements. When the cancel
event has preventDefault called on it, it prevents the dialog element
from being closed because the dialog's DefaultEventHandler won't be
called anymore.
This caused an issue where a new trusted cancel event started being
emitted by file input elements, which unexpectedly caused the dialog to
be closed.
This patch replaces the dialog's DefaultEventHandler with a check to see
if the event was defaultPrevented where it gets emitted in the keyboard
event handler.
Fixed: 1442824
Change-Id: Icce30b3945dd900d90758b4ea3f223008ab0ccd2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4527455
Commit-Queue: Mason Freed <masonf@chromium.org>
Auto-Submit: Joey Arhar <jarhar@chromium.org>
Reviewed-by: Mason Freed <masonf@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1143502}
diff --git a/third_party/blink/renderer/core/html/build.gni b/third_party/blink/renderer/core/html/build.gni
index 8060255..bf312108 100644
--- a/third_party/blink/renderer/core/html/build.gni
+++ b/third_party/blink/renderer/core/html/build.gni
@@ -697,6 +697,7 @@
"html_image_element_test.cc",
"html_link_element_sizes_attribute_test.cc",
"html_link_element_test.cc",
+ "html_dialog_element_test.cc",
"html_meta_element_test.cc",
"html_object_element_test.cc",
"html_plugin_element_test.cc",
diff --git a/third_party/blink/renderer/core/html/html_dialog_element.cc b/third_party/blink/renderer/core/html/html_dialog_element.cc
index b3193acd..ca1bcd9 100644
--- a/third_party/blink/renderer/core/html/html_dialog_element.cc
+++ b/third_party/blink/renderer/core/html/html_dialog_element.cc
@@ -327,16 +327,6 @@
}
}
-void HTMLDialogElement::DefaultEventHandler(Event& event) {
- if (!RuntimeEnabledFeatures::CloseWatcherEnabled() &&
- event.type() == event_type_names::kCancel) {
- close();
- event.SetDefaultHandled();
- return;
- }
- HTMLElement::DefaultEventHandler(event);
-}
-
void HTMLDialogElement::CloseWatcherFiredCancel(Event* close_watcher_event) {
if (!RuntimeEnabledFeatures::CloseWatcherEnabled())
return;
diff --git a/third_party/blink/renderer/core/html/html_dialog_element.h b/third_party/blink/renderer/core/html/html_dialog_element.h
index ce23caf68..29594b8 100644
--- a/third_party/blink/renderer/core/html/html_dialog_element.h
+++ b/third_party/blink/renderer/core/html/html_dialog_element.h
@@ -74,8 +74,6 @@
static void SetFocusForDialogLegacy(HTMLDialogElement* dialog);
private:
- void DefaultEventHandler(Event&) override;
-
void SetIsModal(bool is_modal);
void ScheduleCloseEvent();
diff --git a/third_party/blink/renderer/core/html/html_dialog_element_test.cc b/third_party/blink/renderer/core/html/html_dialog_element_test.cc
new file mode 100644
index 0000000..4fb0917
--- /dev/null
+++ b/third_party/blink/renderer/core/html/html_dialog_element_test.cc
@@ -0,0 +1,27 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/html/html_dialog_element.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/html/html_body_element.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+
+namespace blink {
+
+class HTMLDialogElementTest : public PageTestBase {};
+
+// The dialog event should not be closed in response to cancel events.
+TEST_F(HTMLDialogElementTest, CancelEventDontClose) {
+ auto* dialog = MakeGarbageCollected<HTMLDialogElement>(GetDocument());
+ GetDocument().FirstBodyElement()->AppendChild(dialog);
+ dialog->showModal(ASSERT_NO_EXCEPTION);
+ dialog->DispatchScopedEvent(*Event::CreateBubble(event_type_names::kCancel));
+ EXPECT_TRUE(dialog->FastHasAttribute(html_names::kOpenAttr));
+}
+
+} // namespace blink
diff --git a/third_party/blink/renderer/core/input/keyboard_event_manager.cc b/third_party/blink/renderer/core/input/keyboard_event_manager.cc
index ad9e29c..c130db6 100644
--- a/third_party/blink/renderer/core/input/keyboard_event_manager.cc
+++ b/third_party/blink/renderer/core/input/keyboard_event_manager.cc
@@ -603,6 +603,9 @@
frame_->GetDocument(),
WebFeature::kDialogCloseWatcherCancelSkippedAndDefaultPrevented);
}
+ if (!cancel_event->defaultPrevented()) {
+ dialog->close();
+ }
}
auto* target_node = event->GetEventPath()[0].Target()->ToNode();