Title: [267699] trunk/Source/WebCore
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);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to