- Revision
- 267699
- Author
- [email protected]
- Date
- 2020-09-28 07:55:51 -0700 (Mon, 28 Sep 2020)
Log Message
Crash under DateTimeEditElement::blurFromField
https://bugs.webkit.org/show_bug.cgi?id=216930
<rdar://problem/69308322>
Reviewed by Ryosuke Niwa.
DateTimeEditElement::blurFromField incorrectly invoked
HTMLElement::dispatchBlurEvent, as it was not the element being blurred.
Accessing member variables after this call is unsafe, as there is
nothing protecting the DateTimeEditElement.
To fix, the problematic methods were removed entirely, and replaced
with a new approach to responding to blur events within a DateTimeEditElement.
The blur event's relatedTarget is now compared to the fields within the
DateTimeEditElement, in order to determine when to close the calendar.
This approach is safe, since the relatedTarget is protected by
Document::setFocusedElement.
* html/BaseDateAndTimeInputType.cpp:
(WebCore::BaseDateAndTimeInputType::elementDidBlur): Remove unnecessary call.
If the input has editable fields, closing the calendar is handled by the
new codepath. Running this code unconditionally will result in a flash of the
calendar when clicking on a part of the input type that doesn't contain
an editable field.
* html/shadow/DateTimeEditElement.cpp:
(WebCore::DateTimeEditElement::didBlurFromField):
Check if the event's relatedTarget is another field within the same
DateTimeEditElement. If yes, the calendar should remain open.
* html/shadow/DateTimeEditElement.h:
* html/shadow/DateTimeFieldElement.cpp:
(WebCore::DateTimeFieldElement::defaultEventHandler):
Call handleBlurEvent() if a blur event occurs. This was previously done by
the now-removed dispatchBlurEvent override.
(WebCore::DateTimeFieldElement::handleBlurEvent):
* html/shadow/DateTimeFieldElement.h:
* html/shadow/DateTimeNumericFieldElement.cpp:
(WebCore::DateTimeNumericFieldElement::handleBlurEvent):
* html/shadow/DateTimeNumericFieldElement.h:
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (267698 => 267699)
--- trunk/Source/WebCore/ChangeLog 2020-09-28 14:34:46 UTC (rev 267698)
+++ trunk/Source/WebCore/ChangeLog 2020-09-28 14:55:51 UTC (rev 267699)
@@ -1,3 +1,51 @@
+2020-09-28 Aditya Keerthi <[email protected]>
+
+ Crash under DateTimeEditElement::blurFromField
+ https://bugs.webkit.org/show_bug.cgi?id=216930
+ <rdar://problem/69308322>
+
+ Reviewed by Ryosuke Niwa.
+
+ DateTimeEditElement::blurFromField incorrectly invoked
+ HTMLElement::dispatchBlurEvent, as it was not the element being blurred.
+ Accessing member variables after this call is unsafe, as there is
+ nothing protecting the DateTimeEditElement.
+
+ To fix, the problematic methods were removed entirely, and replaced
+ with a new approach to responding to blur events within a DateTimeEditElement.
+
+ The blur event's relatedTarget is now compared to the fields within the
+ DateTimeEditElement, in order to determine when to close the calendar.
+ This approach is safe, since the relatedTarget is protected by
+ Document::setFocusedElement.
+
+ * html/BaseDateAndTimeInputType.cpp:
+ (WebCore::BaseDateAndTimeInputType::elementDidBlur): Remove unnecessary call.
+
+ If the input has editable fields, closing the calendar is handled by the
+ new codepath. Running this code unconditionally will result in a flash of the
+ calendar when clicking on a part of the input type that doesn't contain
+ an editable field.
+
+ * html/shadow/DateTimeEditElement.cpp:
+ (WebCore::DateTimeEditElement::didBlurFromField):
+
+ Check if the event's relatedTarget is another field within the same
+ DateTimeEditElement. If yes, the calendar should remain open.
+
+ * html/shadow/DateTimeEditElement.h:
+ * html/shadow/DateTimeFieldElement.cpp:
+ (WebCore::DateTimeFieldElement::defaultEventHandler):
+
+ Call handleBlurEvent() if a blur event occurs. This was previously done by
+ the now-removed dispatchBlurEvent override.
+
+ (WebCore::DateTimeFieldElement::handleBlurEvent):
+ * html/shadow/DateTimeFieldElement.h:
+ * html/shadow/DateTimeNumericFieldElement.cpp:
+ (WebCore::DateTimeNumericFieldElement::handleBlurEvent):
+ * html/shadow/DateTimeNumericFieldElement.h:
+
2020-09-28 Antti Koivisto <[email protected]>
[LFC][Integration] Move run iterator to LayoutIntegration namespace
Modified: trunk/Source/WebCore/html/BaseDateAndTimeInputType.cpp (267698 => 267699)
--- trunk/Source/WebCore/html/BaseDateAndTimeInputType.cpp 2020-09-28 14:34:46 UTC (rev 267698)
+++ trunk/Source/WebCore/html/BaseDateAndTimeInputType.cpp 2020-09-28 14:55:51 UTC (rev 267699)
@@ -394,7 +394,8 @@
void BaseDateAndTimeInputType::elementDidBlur()
{
- closeDateTimeChooser();
+ if (!m_dateTimeEditElement)
+ closeDateTimeChooser();
}
void BaseDateAndTimeInputType::detach()
Modified: trunk/Source/WebCore/html/shadow/DateTimeEditElement.cpp (267698 => 267699)
--- trunk/Source/WebCore/html/shadow/DateTimeEditElement.cpp 2020-09-28 14:34:46 UTC (rev 267698)
+++ trunk/Source/WebCore/html/shadow/DateTimeEditElement.cpp 2020-09-28 14:55:51 UTC (rev 267699)
@@ -271,16 +271,21 @@
}
}
-void DateTimeEditElement::blurFromField(RefPtr<Element>&& newFocusedElement)
+void DateTimeEditElement::didBlurFromField(Event& event)
{
- bool notifyOwner = notFound == m_fields.findMatching([&] (auto& field) {
- return field.ptr() == newFocusedElement.get();
- });
+ if (!m_editControlOwner)
+ return;
- HTMLElement::dispatchBlurEvent(WTFMove(newFocusedElement));
+ if (auto* newFocusedElement = event.relatedTarget()) {
+ bool didFocusSiblingField = notFound != m_fields.findMatching([&] (auto& field) {
+ return field.ptr() == newFocusedElement;
+ });
- if (m_editControlOwner && notifyOwner)
- m_editControlOwner->didBlurFromControl();
+ if (didFocusSiblingField)
+ return;
+ }
+
+ m_editControlOwner->didBlurFromControl();
}
void DateTimeEditElement::fieldValueChanged()
Modified: trunk/Source/WebCore/html/shadow/DateTimeEditElement.h (267698 => 267699)
--- trunk/Source/WebCore/html/shadow/DateTimeEditElement.h 2020-09-28 14:34:46 UTC (rev 267698)
+++ trunk/Source/WebCore/html/shadow/DateTimeEditElement.h 2020-09-28 14:55:51 UTC (rev 267699)
@@ -96,7 +96,7 @@
bool focusOnNextFocusableField(size_t startIndex);
// DateTimeFieldElement::FieldOwner functions:
- void blurFromField(RefPtr<Element>&& newFocusedElement) final;
+ void didBlurFromField(Event&) final;
void fieldValueChanged() final;
bool focusOnNextField(const DateTimeFieldElement&) final;
bool focusOnPreviousField(const DateTimeFieldElement&) final;
Modified: trunk/Source/WebCore/html/shadow/DateTimeFieldElement.cpp (267698 => 267699)
--- trunk/Source/WebCore/html/shadow/DateTimeFieldElement.cpp 2020-09-28 14:34:46 UTC (rev 267698)
+++ trunk/Source/WebCore/html/shadow/DateTimeFieldElement.cpp 2020-09-28 14:55:51 UTC (rev 267699)
@@ -60,6 +60,9 @@
void DateTimeFieldElement::defaultEventHandler(Event& event)
{
+ if (event.type() == eventNames().blurEvent)
+ handleBlurEvent(event);
+
if (is<KeyboardEvent>(event)) {
auto& keyboardEvent = downcast<KeyboardEvent>(event);
if (!isFieldOwnerDisabled() && !isFieldOwnerReadOnly()) {
@@ -138,20 +141,12 @@
return HTMLElement::isFocusable();
}
-void DateTimeFieldElement::dispatchBlurEvent(RefPtr<Element>&& newFocusedElement)
+void DateTimeFieldElement::handleBlurEvent(Event& event)
{
if (m_fieldOwner)
- m_fieldOwner->blurFromField(WTFMove(newFocusedElement));
- else
- HTMLElement::dispatchBlurEvent(WTFMove(newFocusedElement));
-
- didBlur();
+ m_fieldOwner->didBlurFromField(event);
}
-void DateTimeFieldElement::didBlur()
-{
-}
-
Locale& DateTimeFieldElement::localeForOwner() const
{
return document().getCachedLocale(localeIdentifier());
Modified: trunk/Source/WebCore/html/shadow/DateTimeFieldElement.h (267698 => 267699)
--- trunk/Source/WebCore/html/shadow/DateTimeFieldElement.h 2020-09-28 14:34:46 UTC (rev 267698)
+++ trunk/Source/WebCore/html/shadow/DateTimeFieldElement.h 2020-09-28 14:55:51 UTC (rev 267699)
@@ -45,7 +45,7 @@
class FieldOwner : public CanMakeWeakPtr<FieldOwner> {
public:
virtual ~FieldOwner();
- virtual void blurFromField(RefPtr<Element>&& newFocusedElement) = 0;
+ virtual void didBlurFromField(Event&) = 0;
virtual void fieldValueChanged() = 0;
virtual bool focusOnNextField(const DateTimeFieldElement&) = 0;
virtual bool focusOnPreviousField(const DateTimeFieldElement&) = 0;
@@ -55,7 +55,6 @@
};
void defaultEventHandler(Event&) override;
- void dispatchBlurEvent(RefPtr<Element>&& newFocusedElement) override;
bool isFocusable() const final;
virtual bool hasValue() const = 0;
@@ -76,9 +75,8 @@
void updateVisibleValue(EventBehavior);
virtual int valueAsInteger() const = 0;
virtual void handleKeyboardEvent(KeyboardEvent&) = 0;
+ virtual void handleBlurEvent(Event&);
- virtual void didBlur();
-
private:
bool supportsFocus() const override;
Modified: trunk/Source/WebCore/html/shadow/DateTimeNumericFieldElement.cpp (267698 => 267699)
--- trunk/Source/WebCore/html/shadow/DateTimeNumericFieldElement.cpp 2020-09-28 14:34:46 UTC (rev 267698)
+++ trunk/Source/WebCore/html/shadow/DateTimeNumericFieldElement.cpp 2020-09-28 14:55:51 UTC (rev 267699)
@@ -163,9 +163,10 @@
keyboardEvent.setDefaultHandled();
}
-void DateTimeNumericFieldElement::didBlur()
+void DateTimeNumericFieldElement::handleBlurEvent(Event& event)
{
m_typeAheadBuffer.clear();
+ DateTimeFieldElement::handleBlurEvent(event);
}
} // namespace WebCore
Modified: trunk/Source/WebCore/html/shadow/DateTimeNumericFieldElement.h (267698 => 267699)
--- trunk/Source/WebCore/html/shadow/DateTimeNumericFieldElement.h 2020-09-28 14:34:46 UTC (rev 267698)
+++ trunk/Source/WebCore/html/shadow/DateTimeNumericFieldElement.h 2020-09-28 14:55:51 UTC (rev 267699)
@@ -66,7 +66,7 @@
// DateTimeFieldElement functions:
String value() const final;
void handleKeyboardEvent(KeyboardEvent&) final;
- void didBlur() final;
+ void handleBlurEvent(Event&) final;
String formatValue(int) const;
void setValueAsIntegerByStepping(int);