[Chromium] REGRESSION(r87067): WebFrame::setFindEndstateFocusAndSelection()
authortkent@chromium.org <tkent@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 30 Jan 2012 07:22:59 +0000 (07:22 +0000)
committertkent@chromium.org <tkent@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 30 Jan 2012 07:22:59 +0000 (07:22 +0000)
doesn't set the selection for <input> and <textarea>
https://bugs.webkit.org/show_bug.cgi?id=77186

Reviewed by Hajime Morita.

When the find-in-page box is closed, WebFrame::stopFinding(false) is
called. It calls setFindEndstateFocusAndSelection(). Before r87067,
m_activeMatch was stored as the normal selection in <input> or
<textarea> by accident. r87067 stopped this accidental behavior.

However the behavior of pre-r87067 is useful and we should support it
for contentEditable elements too.

* src/WebFrameImpl.cpp:
(WebKit::WebFrameImpl::setFindEndstateFocusAndSelection):
- Add special handing for <input> and <textarea> to find a focusable parent.
- Sets the active match as the selection even if a focusable parent is found.
* tests/WebFrameTest.cpp:
(WebKit::TEST_F): Add tests for find() and stopFinding().
* tests/data/find.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@106216 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/src/WebFrameImpl.cpp
Source/WebKit/chromium/tests/WebFrameTest.cpp
Source/WebKit/chromium/tests/data/find.html [new file with mode: 0644]

index 337c378..a4c54d6 100644 (file)
@@ -1,3 +1,27 @@
+2012-01-29  Kent Tamura  <tkent@chromium.org>
+
+        [Chromium] REGRESSION(r87067): WebFrame::setFindEndstateFocusAndSelection()
+        doesn't set the selection for <input> and <textarea>
+        https://bugs.webkit.org/show_bug.cgi?id=77186
+
+        Reviewed by Hajime Morita.
+
+        When the find-in-page box is closed, WebFrame::stopFinding(false) is
+        called. It calls setFindEndstateFocusAndSelection(). Before r87067,
+        m_activeMatch was stored as the normal selection in <input> or
+        <textarea> by accident. r87067 stopped this accidental behavior.
+
+        However the behavior of pre-r87067 is useful and we should support it
+        for contentEditable elements too.
+
+        * src/WebFrameImpl.cpp:
+        (WebKit::WebFrameImpl::setFindEndstateFocusAndSelection):
+        - Add special handing for <input> and <textarea> to find a focusable parent.
+        - Sets the active match as the selection even if a focusable parent is found.
+        * tests/WebFrameTest.cpp:
+        (WebKit::TEST_F): Add tests for find() and stopFinding().
+        * tests/data/find.html: Added.
+
 2012-01-29  Nico Weber  <nicolasweber@gmx.de>
 
         [chromium/mac] Fix two-finger scrolling
index 9d0e0c3..9163e2e 100644 (file)
@@ -2164,11 +2164,18 @@ void WebFrameImpl::setFindEndstateFocusAndSelection()
         // Try to find the first focusable node up the chain, which will, for
         // example, focus links if we have found text within the link.
         Node* node = m_activeMatch->firstNode();
+        if (node && node->isInShadowTree()) {
+            Node* host = node->shadowAncestorNode();
+            if (host->hasTagName(HTMLNames::inputTag) || host->hasTagName(HTMLNames::textareaTag))
+                node = host;
+        }
         while (node && !node->isFocusable() && node != frame()->document())
             node = node->parentNode();
 
         if (node && node != frame()->document()) {
-            // Found a focusable parent node. Set focus to it.
+            // Found a focusable parent node. Set the active match as the
+            // selection and focus to the focusable node.
+            frame()->selection()->setSelection(m_activeMatch.get());
             frame()->document()->setFocusedNode(node);
             return;
         }
index 2b2ea76..b590018 100644 (file)
 #include "FrameTestHelpers.h"
 #include "ResourceError.h"
 #include "WebDocument.h"
+#include "WebFindOptions.h"
 #include "WebFormElement.h"
 #include "WebFrame.h"
 #include "WebFrameClient.h"
+#include "WebRange.h"
 #include "WebScriptSource.h"
 #include "WebSearchableFormData.h"
 #include "WebSecurityPolicy.h"
@@ -379,4 +381,54 @@ TEST_F(WebFrameTest, ContextNotificationsIsolatedWorlds)
     EXPECT_EQ(1, matchCount);
 }
 
+TEST_F(WebFrameTest, FindInPage)
+{
+    registerMockedHttpURLLoad("find.html");
+    WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "find.html");
+    WebFrame* frame = webView->mainFrame();
+    const int findIdentifier = 12345;
+    WebFindOptions options;
+
+    // Find in a <div> element.
+    EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar1"), options, false, 0));
+    frame->stopFinding(false);
+    WebRange range = frame->selectionRange();
+    EXPECT_EQ(5, range.startOffset());
+    EXPECT_EQ(9, range.endOffset());
+    EXPECT_TRUE(frame->document().focusedNode().isNull());
+
+    // Find in an <input> value.
+    EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar2"), options, false, 0));
+    // Confirm stopFinding(false) sets the selection on the found text.
+    frame->stopFinding(false);
+    range = frame->selectionRange();
+    ASSERT_FALSE(range.isNull());
+    EXPECT_EQ(5, range.startOffset());
+    EXPECT_EQ(9, range.endOffset());
+    EXPECT_EQ(WebString::fromUTF8("INPUT"), frame->document().focusedNode().nodeName());
+
+    // Find in a <textarea> content.
+    EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar3"), options, false, 0));
+    // Confirm stopFinding(false) sets the selection on the found text.
+    frame->stopFinding(false);
+    range = frame->selectionRange();
+    ASSERT_FALSE(range.isNull());
+    EXPECT_EQ(5, range.startOffset());
+    EXPECT_EQ(9, range.endOffset());
+    EXPECT_EQ(WebString::fromUTF8("TEXTAREA"), frame->document().focusedNode().nodeName());
+
+    // Find in a contentEditable element.
+    EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar4"), options, false, 0));
+    // Confirm stopFinding(false) sets the selection on the found text.
+    frame->stopFinding(false);
+    range = frame->selectionRange();
+    ASSERT_FALSE(range.isNull());
+    EXPECT_EQ(0, range.startOffset());
+    EXPECT_EQ(4, range.endOffset());
+    // "bar4" is surrounded by <span>, but the focusable node should be the parent <div>.
+    EXPECT_EQ(WebString::fromUTF8("DIV"), frame->document().focusedNode().nodeName());
+
+    webView->close();
+}
+
 } // namespace
diff --git a/Source/WebKit/chromium/tests/data/find.html b/Source/WebKit/chromium/tests/data/find.html
new file mode 100644 (file)
index 0000000..952c823
--- /dev/null
@@ -0,0 +1,6 @@
+<body>
+<div>foo1 bar1 baz1</div>
+<input value="foo2 bar2 baz2">
+<textarea>foo3 bar3 baz3</textarea>
+<div contentEditable="true">foo4 <span>bar4</span> baz4</div>
+</body>