Title: [202147] trunk
Revision
202147
Author
[email protected]
Date
2016-06-16 16:34:17 -0700 (Thu, 16 Jun 2016)

Log Message

Source/WebCore:
[iOS] Focus event dispatched in iframe causes parent document to scroll incorrectly
https://bugs.webkit.org/show_bug.cgi?id=158629
rdar://problem/26521616

Reviewed by Enrica Casucci.

When focussing elements in iframes, the page could scroll to an incorrect location.
This happened because code in Element::focus() tried to disable scrolling on focus,
but did so only for the current frame, so ancestor frames got programmatically scrolled.
On iOS we handle the scrolling in the UI process, so never want the web process to
do programmatic scrolling.

Fix by changing the focus and cache restore code to use SelectionRevealMode::DoNotReveal,
rather than manually prohibiting frame scrolling.

Tests: fast/forms/ios/focus-input-in-iframe.html
       fast/forms/ios/programmatic-focus-input-in-iframe.html

* dom/Element.cpp:
(WebCore::Element::focus):
* history/CachedPage.cpp:
(WebCore::CachedPage::restore):

LayoutTests:
Focus event dispatched in iframe causes parent document to scroll incorrectly
https://bugs.webkit.org/show_bug.cgi?id=158629
rdar://problem/26521616

Reviewed by Enrica Casucci.

Tests for user-initiated and programmatic focus in frames.

* fast/forms/ios/focus-input-in-iframe-expected.txt: Added.
* fast/forms/ios/focus-input-in-iframe.html: Added.
* fast/forms/ios/programmatic-focus-input-in-iframe.html: Added.
* fast/forms/ios/programmatic-focus-input-in-iframe-expected.txt: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (202146 => 202147)


--- trunk/LayoutTests/ChangeLog	2016-06-16 23:27:46 UTC (rev 202146)
+++ trunk/LayoutTests/ChangeLog	2016-06-16 23:34:17 UTC (rev 202147)
@@ -1,3 +1,18 @@
+2016-06-16  Simon Fraser  <[email protected]>
+
+        Focus event dispatched in iframe causes parent document to scroll incorrectly
+        https://bugs.webkit.org/show_bug.cgi?id=158629
+        rdar://problem/26521616
+
+        Reviewed by Enrica Casucci.
+        
+        Tests for user-initiated and programmatic focus in frames.
+
+        * fast/forms/ios/focus-input-in-iframe-expected.txt: Added.
+        * fast/forms/ios/focus-input-in-iframe.html: Added.
+        * fast/forms/ios/programmatic-focus-input-in-iframe.html: Added.
+        * fast/forms/ios/programmatic-focus-input-in-iframe-expected.txt: Added.
+
 2016-06-16  Zalan Bujtas  <[email protected]>
 
         [New Block-Inside-Inline Model] Do not attempt to re-run margin collapsing on the block sequence.

Added: trunk/LayoutTests/fast/forms/ios/focus-input-in-iframe-expected.txt (0 => 202147)


--- trunk/LayoutTests/fast/forms/ios/focus-input-in-iframe-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/focus-input-in-iframe-expected.txt	2016-06-16 23:34:17 UTC (rev 202147)
@@ -0,0 +1,7 @@
+Tests zooming into a text input on tap.
+
+Click to focus input
+
+tap location	{ x: 20.000, y: 62.000 }
+scale	1.455
+visibleRect	{ left: 0.000, top: 1201.976, width: 219.979, height: 329.968 }

Added: trunk/LayoutTests/fast/forms/ios/focus-input-in-iframe.html (0 => 202147)


--- trunk/LayoutTests/fast/forms/ios/focus-input-in-iframe.html	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/focus-input-in-iframe.html	2016-06-16 23:34:17 UTC (rev 202147)
@@ -0,0 +1,48 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+
+<html>
+<head>
+    <meta name="viewport" content="initial-scale=0.5">
+    <style>
+        button {
+            display: block;
+        }
+        iframe {
+            margin-top: 800px;
+        }
+    </style>
+    
+    <script src=""
+    <script>
+    if (window.testRunner) {
+        testRunner.dumpAsText();
+        testRunner.waitUntilDone();
+    }
+
+    if (window.internals)
+        internals.settings.setFrameFlatteningEnabled(true);
+    
+    function buttonClicked()
+    {
+        document.getElementById('frame').contentDocument.getElementById('input').focus();
+    }
+
+    function doTest()
+    {
+        testZoomAfterTap(document.getElementById('target'), 10, 10);
+    }
+
+    window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body>
+
+<p>Tests zooming into a text input on tap.</p>
+<button id="target" _onclick_="buttonClicked()">Click to focus input</button>
+
+<iframe id="frame" srcdoc="<style>input { margin: 400px 20px; }</style>
+<input id='input' type='text'>
+"></iframe>
+
+</body>
+</html>

Added: trunk/LayoutTests/fast/forms/ios/programmatic-focus-input-in-iframe-expected.txt (0 => 202147)


--- trunk/LayoutTests/fast/forms/ios/programmatic-focus-input-in-iframe-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/programmatic-focus-input-in-iframe-expected.txt	2016-06-16 23:34:17 UTC (rev 202147)
@@ -0,0 +1,4 @@
+Tests that a programmatic focus should not scroll into view
+
+PASS: page did not scroll.
+

Added: trunk/LayoutTests/fast/forms/ios/programmatic-focus-input-in-iframe.html (0 => 202147)


--- trunk/LayoutTests/fast/forms/ios/programmatic-focus-input-in-iframe.html	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/programmatic-focus-input-in-iframe.html	2016-06-16 23:34:17 UTC (rev 202147)
@@ -0,0 +1,57 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+
+<html>
+<head>
+    <meta name="viewport" content="initial-scale=0.5">
+    <style>
+        button {
+            display: block;
+        }
+        iframe {
+            margin-top: 800px;
+        }
+    </style>
+    
+    <script>
+    if (window.testRunner) {
+        testRunner.dumpAsText();
+        testRunner.waitUntilDone();
+    }
+    
+    if (window.internals)
+        internals.settings.setFrameFlatteningEnabled(true);
+    
+    function pageDidScroll()
+    {
+        document.getElementById('result').textContent = 'FAIL: page scrolled to ' + document.scrollingElement.scrollTop;
+    }
+
+    function doTest()
+    {
+        window.setTimeout(function() {
+            document.getElementById('frame').contentDocument.getElementById('input').focus();
+        }, 0);
+
+        // Wait for any scroll to happen.
+        window.setTimeout(function() {
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }, 100);
+    }
+
+    window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body _onscroll_="pageDidScroll()">
+
+<p>Tests that a programmatic focus should not scroll into view</p>
+<div id="result">
+    PASS: page did not scroll.
+</div>
+
+<iframe id="frame" srcdoc="<style>input { margin: 400px 20px; }</style>
+<input id='input' type='text'>
+"></iframe>
+
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (202146 => 202147)


--- trunk/Source/WebCore/ChangeLog	2016-06-16 23:27:46 UTC (rev 202146)
+++ trunk/Source/WebCore/ChangeLog	2016-06-16 23:34:17 UTC (rev 202147)
@@ -1,3 +1,28 @@
+2016-06-16  Simon Fraser  <[email protected]>
+
+        [iOS] Focus event dispatched in iframe causes parent document to scroll incorrectly
+        https://bugs.webkit.org/show_bug.cgi?id=158629
+        rdar://problem/26521616
+
+        Reviewed by Enrica Casucci.
+
+        When focussing elements in iframes, the page could scroll to an incorrect location.
+        This happened because code in Element::focus() tried to disable scrolling on focus,
+        but did so only for the current frame, so ancestor frames got programmatically scrolled.
+        On iOS we handle the scrolling in the UI process, so never want the web process to
+        do programmatic scrolling.
+
+        Fix by changing the focus and cache restore code to use SelectionRevealMode::DoNotReveal,
+        rather than manually prohibiting frame scrolling.
+
+        Tests: fast/forms/ios/focus-input-in-iframe.html
+               fast/forms/ios/programmatic-focus-input-in-iframe.html
+
+        * dom/Element.cpp:
+        (WebCore::Element::focus):
+        * history/CachedPage.cpp:
+        (WebCore::CachedPage::restore):
+
 2016-06-16  Zalan Bujtas  <[email protected]>
 
         [New Block-Inside-Inline Model] Do not attempt to re-run margin collapsing on the block sequence.

Modified: trunk/Source/WebCore/dom/Element.cpp (202146 => 202147)


--- trunk/Source/WebCore/dom/Element.cpp	2016-06-16 23:27:46 UTC (rev 202146)
+++ trunk/Source/WebCore/dom/Element.cpp	2016-06-16 23:34:17 UTC (rev 202147)
@@ -2245,6 +2245,8 @@
     }
         
     cancelFocusAppearanceUpdate();
+
+    SelectionRevealMode revealMode = SelectionRevealMode::Reveal;
 #if PLATFORM(IOS)
     // Focusing a form element triggers animation in UIKit to scroll to the right position.
     // Calling updateFocusAppearance() would generate an unnecessary call to ScrollView::setScrollPosition(),
@@ -2252,13 +2254,9 @@
     FrameView* view = document().view();
     bool isFormControl = view && is<HTMLFormControlElement>(*this);
     if (isFormControl)
-        view->setProhibitsScrolling(true);
+        revealMode = SelectionRevealMode::DoNotReveal;
 #endif
-    updateFocusAppearance(restorePreviousSelection ? SelectionRestorationMode::Restore : SelectionRestorationMode::SetDefault);
-#if PLATFORM(IOS)
-    if (isFormControl)
-        view->setProhibitsScrolling(false);
-#endif
+    updateFocusAppearance(restorePreviousSelection ? SelectionRestorationMode::Restore : SelectionRestorationMode::SetDefault, revealMode);
 }
 
 void Element::updateFocusAppearanceAfterAttachIfNeeded()

Modified: trunk/Source/WebCore/history/CachedPage.cpp (202146 => 202147)


--- trunk/Source/WebCore/history/CachedPage.cpp	2016-06-16 23:27:46 UTC (rev 202146)
+++ trunk/Source/WebCore/history/CachedPage.cpp	2016-06-16 23:34:17 UTC (rev 202147)
@@ -77,25 +77,18 @@
     m_cachedMainFrame->open();
     
     // Restore the focus appearance for the focused element.
-    // FIXME: Right now we don't support pages w/ frames in the b/f cache.  This may need to be tweaked when we add support for that.
+    // FIXME: Right now we don't support pages with frames in the b/f cache. This may need to be tweaked when we add support for that.
     Document* focusedDocument = page.focusController().focusedOrMainFrame().document();
     if (Element* element = focusedDocument->focusedElement()) {
+        SelectionRevealMode revealMode = SelectionRevealMode::Reveal;
 #if PLATFORM(IOS)
         // We don't want focused nodes changing scroll position when restoring from the cache
         // as it can cause ugly jumps before we manage to restore the cached position.
         page.mainFrame().selection().suppressScrolling();
-
-        bool hadProhibitsScrolling = false;
-        FrameView* frameView = page.mainFrame().view();
-        if (frameView) {
-            hadProhibitsScrolling = frameView->prohibitsScrolling();
-            frameView->setProhibitsScrolling(true);
-        }
+        revealMode = SelectionRevealMode::DoNotReveal;
 #endif
-        element->updateFocusAppearance(SelectionRestorationMode::Restore);
+        element->updateFocusAppearance(SelectionRestorationMode::Restore, revealMode);
 #if PLATFORM(IOS)
-        if (frameView)
-            frameView->setProhibitsScrolling(hadProhibitsScrolling);
         page.mainFrame().selection().restoreScrolling();
 #endif
     }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to