Title: [196837] trunk
Revision
196837
Author
[email protected]
Date
2016-02-19 14:59:25 -0800 (Fri, 19 Feb 2016)

Log Message

Wheel event callback removing the window causes crash in WebCore.
https://bugs.webkit.org/show_bug.cgi?id=150871

Reviewed by Brent Fulgham.

Source/WebCore:

Null check the FrameView before using it, since the iframe may have been removed
from its parent document inside the event handler.

The new test triggered a cross-load side-effect, where wheel event filtering wasn't
reset between page loads. Fix by calling clearLatchedState() in EventHandler::clear(),
which resets the filtering.

Test: fast/events/wheel-event-destroys-frame.html

* page/EventHandler.cpp:
(WebCore::EventHandler::clear):
* page/WheelEventDeltaFilter.cpp:
(WebCore::WheelEventDeltaFilter::filteredDelta):
* page/mac/EventHandlerMac.mm:
(WebCore::EventHandler::platformCompleteWheelEvent):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::scrollTo):

LayoutTests:

* fast/events/wheel-event-destroys-frame-expected.txt: Added.
* fast/events/wheel-event-destroys-frame.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (196836 => 196837)


--- trunk/LayoutTests/ChangeLog	2016-02-19 22:56:31 UTC (rev 196836)
+++ trunk/LayoutTests/ChangeLog	2016-02-19 22:59:25 UTC (rev 196837)
@@ -1,3 +1,13 @@
+2016-02-19  Simon Fraser  <[email protected]>
+
+        Wheel event callback removing the window causes crash in WebCore.
+        https://bugs.webkit.org/show_bug.cgi?id=150871
+
+        Reviewed by Brent Fulgham.
+
+        * fast/events/wheel-event-destroys-frame-expected.txt: Added.
+        * fast/events/wheel-event-destroys-frame.html: Added.
+
 2016-02-19  Antti Koivisto  <[email protected]>
 
         ComposedTreeIterator traverses normal children for elements with empty shadow root

Added: trunk/LayoutTests/fast/events/wheel-event-destroys-frame-expected.txt (0 => 196837)


--- trunk/LayoutTests/fast/events/wheel-event-destroys-frame-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/wheel-event-destroys-frame-expected.txt	2016-02-19 22:59:25 UTC (rev 196837)
@@ -0,0 +1,3 @@
+This test should not crash
+
+

Added: trunk/LayoutTests/fast/events/wheel-event-destroys-frame.html (0 => 196837)


--- trunk/LayoutTests/fast/events/wheel-event-destroys-frame.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/wheel-event-destroys-frame.html	2016-02-19 22:59:25 UTC (rev 196837)
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script>
+        if (window.testRunner) {
+            testRunner.waitUntilDone();
+            testRunner.dumpAsText();
+        }
+
+        function frameLoaded(iframe)
+        {
+            iframe.contentWindow.addEventListener('wheel', function() {
+                // Removing the window during event firing causes crash.
+                window.document.body.removeChild(iframe);
+                window.setTimeout(function() {
+                    if (window.testRunner)
+                        testRunner.notifyDone();
+                }, 0);
+            });
+
+            if (!window.eventSender)
+                return;
+
+            var iframeTarget = document.getElementById('iframe');
+            var iframeBounds = iframeTarget.getBoundingClientRect();
+
+            eventSender.mouseMoveTo(iframeBounds.left + 10, iframeBounds.top + 10);
+            eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'began', 'none');
+            eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'changed', 'none');
+            eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'changed', 'none');
+            eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'ended', 'none');
+        }
+    </script>
+</head>
+<body>
+    <p>This test should not crash</p>
+    <iframe id="iframe" _onload_="frameLoaded(this)" src="" here</body>"></iframe>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (196836 => 196837)


--- trunk/Source/WebCore/ChangeLog	2016-02-19 22:56:31 UTC (rev 196836)
+++ trunk/Source/WebCore/ChangeLog	2016-02-19 22:59:25 UTC (rev 196837)
@@ -1,3 +1,28 @@
+2016-02-19  Simon Fraser  <[email protected]>
+
+        Wheel event callback removing the window causes crash in WebCore.
+        https://bugs.webkit.org/show_bug.cgi?id=150871
+
+        Reviewed by Brent Fulgham.
+
+        Null check the FrameView before using it, since the iframe may have been removed
+        from its parent document inside the event handler.
+        
+        The new test triggered a cross-load side-effect, where wheel event filtering wasn't
+        reset between page loads. Fix by calling clearLatchedState() in EventHandler::clear(),
+        which resets the filtering.
+
+        Test: fast/events/wheel-event-destroys-frame.html
+
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::clear):
+        * page/WheelEventDeltaFilter.cpp:
+        (WebCore::WheelEventDeltaFilter::filteredDelta):
+        * page/mac/EventHandlerMac.mm:
+        (WebCore::EventHandler::platformCompleteWheelEvent):
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::scrollTo):
+
 2016-02-19  Myles C. Maxfield  <[email protected]>
 
         [Win] [SVG -> OTF Converter] All uses of a font except the first one are invisible

Modified: trunk/Source/WebCore/page/EventHandler.cpp (196836 => 196837)


--- trunk/Source/WebCore/page/EventHandler.cpp	2016-02-19 22:56:31 UTC (rev 196836)
+++ trunk/Source/WebCore/page/EventHandler.cpp	2016-02-19 22:59:25 UTC (rev 196837)
@@ -452,9 +452,7 @@
     m_mousePressed = false;
     m_capturesDragging = false;
     m_capturingMouseEventsElement = nullptr;
-#if PLATFORM(MAC)
-    m_frame.mainFrame().resetLatchingState();
-#endif
+    clearLatchedState();
 #if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
     m_originatingTouchPointTargets.clear();
     m_originatingTouchPointDocument = nullptr;
@@ -2664,7 +2662,8 @@
 #if PLATFORM(MAC)
     m_frame.mainFrame().resetLatchingState();
 #endif
-    m_frame.mainFrame().wheelEventDeltaFilter()->endFilteringDeltas();
+    if (WheelEventDeltaFilter* filter = m_frame.mainFrame().wheelEventDeltaFilter())
+        filter->endFilteringDeltas();
 }
 
 void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent* wheelEvent)

Modified: trunk/Source/WebCore/page/WheelEventDeltaFilter.cpp (196836 => 196837)


--- trunk/Source/WebCore/page/WheelEventDeltaFilter.cpp	2016-02-19 22:56:31 UTC (rev 196836)
+++ trunk/Source/WebCore/page/WheelEventDeltaFilter.cpp	2016-02-19 22:59:25 UTC (rev 196837)
@@ -31,6 +31,8 @@
 #endif
 
 #include "FloatSize.h"
+#include "Logging.h"
+#include "TextStream.h"
 
 namespace WebCore {
     
@@ -58,6 +60,7 @@
 
 FloatSize WheelEventDeltaFilter::filteredDelta() const
 {
+    LOG_WITH_STREAM(Scrolling, stream << "BasicWheelEventDeltaFilter::filteredDelta returning " << m_currentFilteredDelta);
     return m_currentFilteredDelta;
 }
 

Modified: trunk/Source/WebCore/page/mac/EventHandlerMac.mm (196836 => 196837)


--- trunk/Source/WebCore/page/mac/EventHandlerMac.mm	2016-02-19 22:56:31 UTC (rev 196836)
+++ trunk/Source/WebCore/page/mac/EventHandlerMac.mm	2016-02-19 22:59:25 UTC (rev 196837)
@@ -1008,9 +1008,10 @@
 
 bool EventHandler::platformCompleteWheelEvent(const PlatformWheelEvent& wheelEvent, ContainerNode* scrollableContainer, ScrollableArea* scrollableArea)
 {
+    FrameView* view = m_frame.view();
     // We do another check on the frame view because the event handler can run JS which results in the frame getting destroyed.
-    ASSERT(m_frame.view());
-    FrameView* view = m_frame.view();
+    if (!view)
+        return false;
 
     ScrollLatchingState* latchingState = m_frame.mainFrame().latchingState();
     if (wheelEvent.useLatchedEventElement() && !latchingIsLockedToAncestorOfThisFrame(m_frame) && latchingState && latchingState->scrollableContainer()) {

Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (196836 => 196837)


--- trunk/Source/WebCore/rendering/RenderLayer.cpp	2016-02-19 22:56:31 UTC (rev 196836)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp	2016-02-19 22:59:25 UTC (rev 196837)
@@ -2349,6 +2349,8 @@
     if (!box)
         return;
 
+    LOG_WITH_STREAM(Scrolling, stream << "RenderLayer::scrollTo " << position);
+
     ScrollPosition newPosition = position;
     if (box->style().overflowX() != OMARQUEE) {
         // Ensure that the dimensions will be computed if they need to be (for overflow:hidden blocks).
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to