Changeset 208003 in webkit


Ignore:
Timestamp:
Oct 27, 2016 1:56:17 PM (7 years ago)
Author:
Brent Fulgham
Message:

Prevent hit tests from being performed on an invalid render tree
https://bugs.webkit.org/show_bug.cgi?id=163877
<rdar://problem/28675761>

Reviewed by Simon Fraser.

Source/WebCore:

Changeset r200971 added code to ensure that layout is up-to-date before hit testing, but did
so only for the main frame. It was still possible to enter cross-frame hit testing with a
subframe needing style recalc. In that situation, the subframe's updateLayout() would get
called, which could trigger a compositing change that marked the parent frame as needing style
recalc. A subsequent layout on the parent frame (for example by hit testing traversing into
a second subframe) could then mutate the parent frame's layer tree while hit testing was
traversing it.

This patch modifies the hit test logic to ensure that a recursive layout is performed so that
we always perform hit tests on a clean set of frames. It also adds some assertions to warn
us if we encounter this invalid state.

Tested by fast/layers/prevent-hit-test-during-layout.html.

  • dom/Document.cpp:

(WebCore::Document::scheduleStyleRecalc): Assert that we are not hit testing
during style recalculation.

  • page/EventHandler.cpp:

(WebCore::EventHandler::hitTestResultAtPoint): Ensure that we have a clean render tree
when hit testing.

  • page/FrameView.cpp:

(WebCore::FrameView::setNeedsLayout): Assert that we are not in the process of hit testing
when we schedule a layout.

  • rendering/RenderView.cpp:

(WebCore::RenderView::hitTest): Mark RenderView as in an active hit test.

  • rendering/RenderView.h:

LayoutTests:

  • fast/layers/prevent-hit-test-during-layout-expected.txt: Added.
  • fast/layers/prevent-hit-test-during-layout.html: Added.
  • platform/efl/TestExpectations: Skip on this platform.
  • platform/gtk/TestExpectations: Skip on this platform.
  • platform/ios-simulator/TestExpectations: Skip on this platform.
  • platform/win/TestExpectations: Skip on this platform.
Location:
trunk
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r208000 r208003  
     12016-10-25  Brent Fulgham  <bfulgham@apple.com>
     2
     3        Prevent hit tests from being performed on an invalid render tree
     4        https://bugs.webkit.org/show_bug.cgi?id=163877
     5        <rdar://problem/28675761>
     6
     7        Reviewed by Simon Fraser.
     8
     9        * fast/layers/prevent-hit-test-during-layout-expected.txt: Added.
     10        * fast/layers/prevent-hit-test-during-layout.html: Added.
     11        * platform/efl/TestExpectations: Skip on this platform.
     12        * platform/gtk/TestExpectations: Skip on this platform.
     13        * platform/ios-simulator/TestExpectations: Skip on this platform.
     14        * platform/win/TestExpectations: Skip on this platform.
     15
    1162016-10-27  Chris Dumez  <cdumez@apple.com>
    217
  • trunk/LayoutTests/platform/efl/TestExpectations

    r207989 r208003  
    596596security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html [ Skip ]
    597597security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html [ Skip ]
     598
     599# Only Mac has implemented DictionaryLookup
     600fast/layers/prevent-hit-test-during-layout.html [ Skip ]
    598601
    599602#////////////////////////////////////////////////////////////////////////////////////////
  • trunk/LayoutTests/platform/gtk/TestExpectations

    r207989 r208003  
    17041704webkit.org/b/152247 fast/forms/input-appearance-spinbutton.html [ Skip ]
    17051705webkit.org/b/152247 fast/forms/listbox-scrollbar-hit-test.html [ Skip ]
     1706
     1707# Only Mac has implemented DictionaryLookup
     1708fast/layers/prevent-hit-test-during-layout.html [ Skip ]
    17061709
    17071710#////////////////////////////////////////////////////////////////////////////////////////
  • trunk/LayoutTests/platform/ios-simulator/TestExpectations

    r207841 r208003  
    27322732
    27332733webkit.org/b/158836 imported/w3c/web-platform-tests/encrypted-media [ Skip ]
     2734
     2735# Only Mac has implemented DictionaryLookup
     2736fast/layers/prevent-hit-test-during-layout.html [ Skip ]
  • trunk/LayoutTests/platform/win/TestExpectations

    r207660 r208003  
    36233623# html/syntax web platform tests are failing on Windows.
    36243624webkit.org/b/162415 imported/w3c/web-platform-tests/html/syntax [ Skip ]
     3625
     3626# Only Mac has implemented DictionaryLookup
     3627fast/layers/prevent-hit-test-during-layout.html [ Skip ]
  • trunk/Source/WebCore/ChangeLog

    r208002 r208003  
     12016-10-27  Brent Fulgham  <bfulgham@apple.com>
     2
     3        Prevent hit tests from being performed on an invalid render tree
     4        https://bugs.webkit.org/show_bug.cgi?id=163877
     5        <rdar://problem/28675761>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Changeset r200971 added code to ensure that layout is up-to-date before hit testing, but did
     10        so only for the main frame. It was still possible to enter cross-frame hit testing with a
     11        subframe needing style recalc. In that situation, the subframe's updateLayout() would get
     12        called, which could trigger a compositing change that marked the parent frame as needing style
     13        recalc. A subsequent layout on the parent frame (for example by hit testing traversing into
     14        a second subframe) could then mutate the parent frame's layer tree while hit testing was
     15        traversing it.
     16       
     17        This patch modifies the hit test logic to ensure that a recursive layout is performed so that
     18        we always perform hit tests on a clean set of frames. It also adds some assertions to warn
     19        us if we encounter this invalid state.
     20
     21        Tested by fast/layers/prevent-hit-test-during-layout.html.
     22
     23        * dom/Document.cpp:
     24        (WebCore::Document::scheduleStyleRecalc): Assert that we are not hit testing
     25        during style recalculation.
     26        * page/EventHandler.cpp:
     27        (WebCore::EventHandler::hitTestResultAtPoint): Ensure that we have a clean render tree
     28        when hit testing.
     29        * page/FrameView.cpp:
     30        (WebCore::FrameView::setNeedsLayout): Assert that we are not in the process of hit testing
     31        when we schedule a layout.
     32        * rendering/RenderView.cpp:
     33        (WebCore::RenderView::hitTest): Mark RenderView as in an active hit test.
     34        * rendering/RenderView.h:
     35
    1362016-10-27  Zan Dobersek  <zdobersek@igalia.com>
    237
  • trunk/Source/WebCore/dom/Document.cpp

    r207810 r208003  
    17561756void Document::scheduleStyleRecalc()
    17571757{
     1758    ASSERT(!m_renderView || !m_renderView->inHitTesting());
     1759
    17581760    if (m_styleRecalcTimer.isActive() || pageCacheState() != NotInPageCache)
    17591761        return;
  • trunk/Source/WebCore/page/EventHandler.cpp

    r207689 r208003  
    11461146    unsigned nonNegativePaddingWidth = std::max<LayoutUnit>(0, padding.width()).toUnsigned();
    11471147    unsigned nonNegativePaddingHeight = std::max<LayoutUnit>(0, padding.height()).toUnsigned();
     1148
    11481149    // We should always start hit testing a clean tree.
    1149     if (m_frame.document())
    1150         m_frame.document()->updateLayoutIgnorePendingStylesheets();
     1150    if (auto* frameView = m_frame.view())
     1151        frameView->updateLayoutAndStyleIfNeededRecursive();
     1152
    11511153    HitTestResult result(point, nonNegativePaddingHeight, nonNegativePaddingWidth, nonNegativePaddingHeight, nonNegativePaddingWidth);
    11521154    RenderView* renderView = m_frame.contentRenderer();
  • trunk/Source/WebCore/page/FrameView.cpp

    r207814 r208003  
    28462846    }
    28472847
    2848     if (RenderView* renderView = this->renderView())
     2848    if (auto* renderView = this->renderView()) {
     2849        ASSERT(!renderView->inHitTesting());
    28492850        renderView->setNeedsLayout();
     2851    }
    28502852}
    28512853
  • trunk/Source/WebCore/rendering/RenderView.cpp

    r206538 r208003  
    5353#include "TransformState.h"
    5454#include <wtf/StackStats.h>
     55#include <wtf/TemporaryChange.h>
    5556
    5657namespace WebCore {
     
    184185{
    185186    document().updateLayout();
     187   
     188#if !ASSERT_DISABLED
     189    TemporaryChange<bool> hitTestRestorer { m_inHitTesting, true };
     190#endif
    186191
    187192    FrameFlatteningLayoutDisallower disallower(frameView());
  • trunk/Source/WebCore/rendering/RenderView.h

    r204400 r208003  
    11/*
    22 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
    3  * Copyright (C) 2006, 2015 Apple Inc.
     3 * Copyright (C) 2006, 2015-2016 Apple Inc.
    44 *
    55 * This library is free software; you can redistribute it and/or
     
    251251#endif
    252252
     253#if !ASSERT_DISABLED
     254    bool inHitTesting() const { return m_inHitTesting; }
     255#endif
     256
    253257protected:
    254258    void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags, bool* wasFixed) const override;
     
    361365    bool m_usesFirstLineRules { false };
    362366    bool m_usesFirstLetterRules { false };
     367#if !ASSERT_DISABLED
     368    bool m_inHitTesting { false };
     369#endif
    363370
    364371    HashSet<RenderElement*> m_renderersWithPausedImageAnimation;
Note: See TracChangeset for help on using the changeset viewer.