Title: [187593] trunk
- Revision
- 187593
- Author
- simon.fra...@apple.com
- Date
- 2015-07-30 11:32:45 -0700 (Thu, 30 Jul 2015)
Log Message
Selecting in an iframe can cause main page scrolling
https://bugs.webkit.org/show_bug.cgi?id=147431
rdar://problem/19244589
Reviewed by Zalan Bujtas.
Source/WebCore:
The RenderLayer auatoscroll code walks up the RenderLayer hierarchy, crossing
frame boundaries. However, as it crosses into an ancestor frame it failed to
map the target rect into the coordinate space of the new frame, which caused
us to scroll to an incorrect location in that parent frame.
Test: fast/events/autoscroll-in-iframe.html
* rendering/RenderLayer.cpp:
(WebCore::parentLayerCrossFrame): Make the layer a reference, and pass in
an optional rect. When crossing frame boundaries, map the rect from the
contents of the child frame to the contents of the parent frame.
(WebCore::RenderLayer::enclosingScrollableLayer): Pass optional rect.
(WebCore::RenderLayer::scrollRectToVisible):
(WebCore::RenderLayer::hasScrollableOrRubberbandableAncestor):
* rendering/RenderLayer.h:
LayoutTests:
Test that uses eventSender to select in an iframe after scrolling the
main page.
* fast/events/autoscroll-in-iframe-expected.txt: Added.
* fast/events/autoscroll-in-iframe.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (187592 => 187593)
--- trunk/LayoutTests/ChangeLog 2015-07-30 18:31:01 UTC (rev 187592)
+++ trunk/LayoutTests/ChangeLog 2015-07-30 18:32:45 UTC (rev 187593)
@@ -1,3 +1,17 @@
+2015-07-30 Simon Fraser <simon.fra...@apple.com>
+
+ Selecting in an iframe can cause main page scrolling
+ https://bugs.webkit.org/show_bug.cgi?id=147431
+ rdar://problem/19244589
+
+ Reviewed by Zalan Bujtas.
+
+ Test that uses eventSender to select in an iframe after scrolling the
+ main page.
+
+ * fast/events/autoscroll-in-iframe-expected.txt: Added.
+ * fast/events/autoscroll-in-iframe.html: Added.
+
2015-07-29 Matt Rajca <mra...@apple.com>
Media Session: test Next/Previous Track media control events delivered to Content media sessions
Added: trunk/LayoutTests/fast/events/autoscroll-in-iframe-expected.txt (0 => 187593)
--- trunk/LayoutTests/fast/events/autoscroll-in-iframe-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/events/autoscroll-in-iframe-expected.txt 2015-07-30 18:32:45 UTC (rev 187593)
@@ -0,0 +1,3 @@
+
+PASSED: selecting in the iframe did not scroll the page.
+
Added: trunk/LayoutTests/fast/events/autoscroll-in-iframe.html (0 => 187593)
--- trunk/LayoutTests/fast/events/autoscroll-in-iframe.html (rev 0)
+++ trunk/LayoutTests/fast/events/autoscroll-in-iframe.html 2015-07-30 18:32:45 UTC (rev 187593)
@@ -0,0 +1,89 @@
+<html>
+ <head>
+ <style>
+ body {
+ height: 2000px;
+ }
+ iframe {
+ position: absolute;
+ top: 800px;
+ }
+ </style>
+ <script src=""
+ <script>
+
+ if (window.testRunner) {
+ testRunner.waitUntilDone();
+ testRunner.dumpAsText();
+ }
+
+ function log(msg)
+ {
+ document.getElementById('console').appendChild(document.createTextNode(msg + '\n'));
+ }
+
+ var verticalScrollOffset;
+ var iframe;
+
+ function doTest()
+ {
+ document.scrollingElement.scrollTop = 800;
+ if (document.scrollingElement.scrollTop != 800)
+ log("FAILED: failed to scroll by 800px");
+
+ iframe = document.getElementById('targetFrame');
+
+ var textInIframe = iframe.contentDocument.getElementById('starthere');
+ var x = iframe.clientLeft + textInIframe.offsetLeft + 7;
+ var y = iframe.clientTop + textInIframe.offsetTop + 7;
+ if (window.eventSender) {
+ eventSender.dragMode = false;
+ eventSender.mouseMoveTo(x, y);
+ eventSender.mouseDown();
+ eventSender.mouseUp();
+ }
+ setTimeout(autoscrollTestPart1, 0);
+ }
+
+ function autoscrollTestPart1()
+ {
+ var mainDocumentTop = document.scrollingElement.scrollTop;
+ if (mainDocumentTop != 800)
+ log("FAILED: Clicking in the iframe scrolled the page (window.scrollTops is " + mainDocumentTop + ")");
+
+ if (window.eventSender) {
+ var textInIframe = iframe.contentDocument.getElementById('starthere');
+ var x = iframe.clientLeft + textInIframe.offsetLeft + 7;
+ var y = iframe.clientTop + textInIframe.offsetTop + 7;
+ eventSender.dragMode = false;
+ eventSender.mouseMoveTo(x, y);
+ eventSender.mouseDown();
+ eventSender.mouseMoveTo(x + 10, y);
+ }
+ setTimeout(autoscrollTestPart2, 100);
+ }
+
+ function autoscrollTestPart2()
+ {
+ if (window.eventSender)
+ eventSender.mouseUp();
+
+ var mainDocumentTop = document.scrollingElement.scrollTop;
+ if (mainDocumentTop == 800)
+ log("PASSED: selecting in the iframe did not scroll the page.");
+ else
+ log("FAILED: the page autoscrolled (window.scrollTop is " + mainDocumentTop + ").");
+
+ if (window.testRunner)
+ testRunner.notifyDone();
+ }
+
+ window.addEventListener('load', doTest, false);
+ </script>
+ </head>
+<body>
+ <iframe id="targetFrame" srcdoc="<!DOCTYPE html><html><body><div id='starthere' style='height:60px; overflow:auto;'>asdf<br>asdf<br>asdf<br>asdf<br>asdf"></iframe>
+ <div id="console"></div>
+</body>
+</html>
+
Modified: trunk/Source/WebCore/ChangeLog (187592 => 187593)
--- trunk/Source/WebCore/ChangeLog 2015-07-30 18:31:01 UTC (rev 187592)
+++ trunk/Source/WebCore/ChangeLog 2015-07-30 18:32:45 UTC (rev 187593)
@@ -1,5 +1,29 @@
2015-07-30 Simon Fraser <simon.fra...@apple.com>
+ Selecting in an iframe can cause main page scrolling
+ https://bugs.webkit.org/show_bug.cgi?id=147431
+ rdar://problem/19244589
+
+ Reviewed by Zalan Bujtas.
+
+ The RenderLayer auatoscroll code walks up the RenderLayer hierarchy, crossing
+ frame boundaries. However, as it crosses into an ancestor frame it failed to
+ map the target rect into the coordinate space of the new frame, which caused
+ us to scroll to an incorrect location in that parent frame.
+
+ Test: fast/events/autoscroll-in-iframe.html
+
+ * rendering/RenderLayer.cpp:
+ (WebCore::parentLayerCrossFrame): Make the layer a reference, and pass in
+ an optional rect. When crossing frame boundaries, map the rect from the
+ contents of the child frame to the contents of the parent frame.
+ (WebCore::RenderLayer::enclosingScrollableLayer): Pass optional rect.
+ (WebCore::RenderLayer::scrollRectToVisible):
+ (WebCore::RenderLayer::hasScrollableOrRubberbandableAncestor):
+ * rendering/RenderLayer.h:
+
+2015-07-30 Simon Fraser <simon.fra...@apple.com>
+
Improve the history logging output
https://bugs.webkit.org/show_bug.cgi?id=147429
Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (187592 => 187593)
--- trunk/Source/WebCore/rendering/RenderLayer.cpp 2015-07-30 18:31:01 UTC (rev 187592)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp 2015-07-30 18:32:45 UTC (rev 187593)
@@ -1449,13 +1449,12 @@
return curr;
}
-static RenderLayer* parentLayerCrossFrame(const RenderLayer* layer)
+static RenderLayer* parentLayerCrossFrame(const RenderLayer& layer, LayoutRect* rect = nullptr)
{
- ASSERT(layer);
- if (layer->parent())
- return layer->parent();
+ if (layer.parent())
+ return layer.parent();
- HTMLFrameOwnerElement* ownerElement = layer->renderer().document().ownerElement();
+ HTMLFrameOwnerElement* ownerElement = layer.renderer().document().ownerElement();
if (!ownerElement)
return nullptr;
@@ -1463,12 +1462,18 @@
if (!ownerRenderer)
return nullptr;
+ // Convert the rect into the coordinate space of the parent frame's document.
+ if (rect) {
+ IntRect viewRect = layer.renderer().frame().view()->convertToContainingView(enclosingIntRect(*rect));
+ *rect = ownerRenderer->frame().view()->viewToContents(viewRect);
+ }
+
return ownerRenderer->enclosingLayer();
}
-RenderLayer* RenderLayer::enclosingScrollableLayer() const
+RenderLayer* RenderLayer::enclosingScrollableLayer(LayoutRect* rect) const
{
- for (RenderLayer* nextLayer = parentLayerCrossFrame(this); nextLayer; nextLayer = parentLayerCrossFrame(nextLayer)) {
+ for (RenderLayer* nextLayer = parentLayerCrossFrame(*this, rect); nextLayer; nextLayer = parentLayerCrossFrame(*nextLayer, rect)) {
if (is<RenderBox>(nextLayer->renderer()) && downcast<RenderBox>(nextLayer->renderer()).canBeScrolledAndHasScrollableArea())
return nextLayer;
}
@@ -2531,7 +2536,7 @@
}
if (renderer().frame().eventHandler().autoscrollInProgress())
- parentLayer = enclosingScrollableLayer();
+ parentLayer = enclosingScrollableLayer(&newRect);
if (parentLayer)
parentLayer->scrollRectToVisible(newRect, alignX, alignY);
@@ -3182,7 +3187,7 @@
bool RenderLayer::hasScrollableOrRubberbandableAncestor()
{
- for (RenderLayer* nextLayer = parentLayerCrossFrame(this); nextLayer; nextLayer = parentLayerCrossFrame(nextLayer)) {
+ for (RenderLayer* nextLayer = parentLayerCrossFrame(*this); nextLayer; nextLayer = parentLayerCrossFrame(*nextLayer)) {
if (nextLayer->isScrollableOrRubberbandable())
return true;
}
Modified: trunk/Source/WebCore/rendering/RenderLayer.h (187592 => 187593)
--- trunk/Source/WebCore/rendering/RenderLayer.h 2015-07-30 18:31:01 UTC (rev 187592)
+++ trunk/Source/WebCore/rendering/RenderLayer.h 2015-07-30 18:32:45 UTC (rev 187593)
@@ -404,7 +404,7 @@
RenderLayer* enclosingAncestorForPosition(EPosition) const;
// Returns the nearest enclosing layer that is scrollable.
- RenderLayer* enclosingScrollableLayer() const;
+ RenderLayer* enclosingScrollableLayer(LayoutRect* = nullptr) const;
// The layer relative to which clipping rects for this layer are computed.
RenderLayer* clippingRootForPainting() const;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes