⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 267699 in webkit


Ignore:
Timestamp:
Sep 28, 2020, 7:55:51 AM (6 years ago)
Author:
Aditya Keerthi
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:
Location:
trunk/Source/WebCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r267697 r267699  
     12020-09-28  Aditya Keerthi  <akeerthi@apple.com>
     2
     3        Crash under DateTimeEditElement::blurFromField
     4        https://bugs.webkit.org/show_bug.cgi?id=216930
     5        <rdar://problem/69308322>
     6
     7        Reviewed by Ryosuke Niwa.
     8
     9        DateTimeEditElement::blurFromField incorrectly invoked
     10        HTMLElement::dispatchBlurEvent, as it was not the element being blurred.
     11        Accessing member variables after this call is unsafe, as there is
     12        nothing protecting the DateTimeEditElement.
     13
     14        To fix, the problematic methods were removed entirely, and replaced
     15        with a new approach to responding to blur events within a DateTimeEditElement.
     16
     17        The blur event's relatedTarget is now compared to the fields within the
     18        DateTimeEditElement, in order to determine when to close the calendar.
     19        This approach is safe, since the relatedTarget is protected by
     20        Document::setFocusedElement.
     21
     22        * html/BaseDateAndTimeInputType.cpp:
     23        (WebCore::BaseDateAndTimeInputType::elementDidBlur): Remove unnecessary call.
     24
     25        If the input has editable fields, closing the calendar is handled by the
     26        new codepath. Running this code unconditionally will result in a flash of the
     27        calendar when clicking on a part of the input type that doesn't contain
     28        an editable field.
     29
     30        * html/shadow/DateTimeEditElement.cpp:
     31        (WebCore::DateTimeEditElement::didBlurFromField):
     32
     33        Check if the event's relatedTarget is another field within the same
     34        DateTimeEditElement. If yes, the calendar should remain open.
     35
     36        * html/shadow/DateTimeEditElement.h:
     37        * html/shadow/DateTimeFieldElement.cpp:
     38        (WebCore::DateTimeFieldElement::defaultEventHandler):
     39
     40        Call handleBlurEvent() if a blur event occurs. This was previously done by
     41        the now-removed dispatchBlurEvent override.
     42
     43        (WebCore::DateTimeFieldElement::handleBlurEvent):
     44        * html/shadow/DateTimeFieldElement.h:
     45        * html/shadow/DateTimeNumericFieldElement.cpp:
     46        (WebCore::DateTimeNumericFieldElement::handleBlurEvent):
     47        * html/shadow/DateTimeNumericFieldElement.h:
     48
    1492020-09-28  Antti Koivisto  <antti@apple.com>
    250
  • trunk/Source/WebCore/html/BaseDateAndTimeInputType.cpp

    r267003 r267699  
    395395void BaseDateAndTimeInputType::elementDidBlur()
    396396{
    397     closeDateTimeChooser();
     397    if (!m_dateTimeEditElement)
     398        closeDateTimeChooser();
    398399}
    399400
  • trunk/Source/WebCore/html/shadow/DateTimeEditElement.cpp

    r267074 r267699  
    272272}
    273273
    274 void DateTimeEditElement::blurFromField(RefPtr<Element>&& newFocusedElement)
    275 {
    276     bool notifyOwner = notFound == m_fields.findMatching([&] (auto& field) {
    277         return field.ptr() == newFocusedElement.get();
    278     });
    279 
    280     HTMLElement::dispatchBlurEvent(WTFMove(newFocusedElement));
    281 
    282     if (m_editControlOwner && notifyOwner)
    283         m_editControlOwner->didBlurFromControl();
     274void DateTimeEditElement::didBlurFromField(Event& event)
     275{
     276    if (!m_editControlOwner)
     277        return;
     278
     279    if (auto* newFocusedElement = event.relatedTarget()) {
     280        bool didFocusSiblingField = notFound != m_fields.findMatching([&] (auto& field) {
     281            return field.ptr() == newFocusedElement;
     282        });
     283
     284        if (didFocusSiblingField)
     285            return;
     286    }
     287
     288    m_editControlOwner->didBlurFromControl();
    284289}
    285290
  • trunk/Source/WebCore/html/shadow/DateTimeEditElement.h

    r266779 r267699  
    9797
    9898    // DateTimeFieldElement::FieldOwner functions:
    99     void blurFromField(RefPtr<Element>&& newFocusedElement) final;
     99    void didBlurFromField(Event&) final;
    100100    void fieldValueChanged() final;
    101101    bool focusOnNextField(const DateTimeFieldElement&) final;
  • trunk/Source/WebCore/html/shadow/DateTimeFieldElement.cpp

    r267281 r267699  
    6161void DateTimeFieldElement::defaultEventHandler(Event& event)
    6262{
     63    if (event.type() == eventNames().blurEvent)
     64        handleBlurEvent(event);
     65
    6366    if (is<KeyboardEvent>(event)) {
    6467        auto& keyboardEvent = downcast<KeyboardEvent>(event);
     
    139142}
    140143
    141 void DateTimeFieldElement::dispatchBlurEvent(RefPtr<Element>&& newFocusedElement)
     144void DateTimeFieldElement::handleBlurEvent(Event& event)
    142145{
    143146    if (m_fieldOwner)
    144         m_fieldOwner->blurFromField(WTFMove(newFocusedElement));
    145     else
    146         HTMLElement::dispatchBlurEvent(WTFMove(newFocusedElement));
    147 
    148     didBlur();
    149 }
    150 
    151 void DateTimeFieldElement::didBlur()
    152 {
     147        m_fieldOwner->didBlurFromField(event);
    153148}
    154149
  • trunk/Source/WebCore/html/shadow/DateTimeFieldElement.h

    r266524 r267699  
    4646    public:
    4747        virtual ~FieldOwner();
    48         virtual void blurFromField(RefPtr<Element>&& newFocusedElement) = 0;
     48        virtual void didBlurFromField(Event&) = 0;
    4949        virtual void fieldValueChanged() = 0;
    5050        virtual bool focusOnNextField(const DateTimeFieldElement&) = 0;
     
    5656
    5757    void defaultEventHandler(Event&) override;
    58     void dispatchBlurEvent(RefPtr<Element>&& newFocusedElement) override;
    5958    bool isFocusable() const final;
    6059
     
    7776    virtual int valueAsInteger() const = 0;
    7877    virtual void handleKeyboardEvent(KeyboardEvent&) = 0;
    79 
    80     virtual void didBlur();
     78    virtual void handleBlurEvent(Event&);
    8179
    8280private:
  • trunk/Source/WebCore/html/shadow/DateTimeNumericFieldElement.cpp

    r266779 r267699  
    164164}
    165165
    166 void DateTimeNumericFieldElement::didBlur()
     166void DateTimeNumericFieldElement::handleBlurEvent(Event& event)
    167167{
    168168    m_typeAheadBuffer.clear();
     169    DateTimeFieldElement::handleBlurEvent(event);
    169170}
    170171
  • trunk/Source/WebCore/html/shadow/DateTimeNumericFieldElement.h

    r266779 r267699  
    6767    String value() const final;
    6868    void handleKeyboardEvent(KeyboardEvent&) final;
    69     void didBlur() final;
     69    void handleBlurEvent(Event&) final;
    7070
    7171    String formatValue(int) const;
Note: See TracChangeset for help on using the changeset viewer.