Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(286)

Unified Diff: third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp

Issue 2841093002: Algorithm for deciding if a frame's selection should be hidden (Closed)
Patch Set: 2 more tests for selections in shadow trees Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
diff --git a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
index 67b5b56b54dbad9f382ac7be1078763930e9ab19..b92656380efa299f1757be073127c887d65dcd01 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
@@ -349,4 +349,563 @@ TEST_F(FrameSelectionTest, SelectInvalidPositionInFlatTreeDoesntCrash) {
EXPECT_EQ(PositionInFlatTree(foo, 0), selection.Extent());
}
+TEST_F(FrameSelectionTest, CaretInShadowTree) {
+ SetBodyContent("<p id=host></p>bar");
+ ShadowRoot* shadow_root =
+ SetShadowContent("<div contenteditable id='ce'>foo</div>", "host");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const ce = shadow_root->getElementById("ce");
+ ce->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ ce->blur(); // Move focus to document body.
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden()); // Caret is now hidden.
Xiaocheng 2017/05/08 22:08:29 nit: When documenting an EXPECT_FOO (or ASSERT_FOO
hugoh_UTC2 2017/05/09 09:22:45 Here I found it to messy to add a comment for ever
+}
+
+TEST_F(FrameSelectionTest, CaretInTextControl) {
+ SetBodyContent("<input id='field'>"); // <input> hosts a shadow tree.
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const field = GetDocument().getElementById("field");
+ field->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ field->blur(); // Move focus to document body.
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden()); // Caret is now hidden.
+}
+
+TEST_F(FrameSelectionTest, RangeInShadowTree) {
Xiaocheng 2017/05/08 22:08:29 Sorry if I made a confusion. I was expecting a tes
hugoh_UTC2 2017/05/09 09:22:45 Done in PS12.
+ SetBodyContent("<p id='host'></p>");
+ ShadowRoot* shadow_root = SetShadowContent("hey", "host");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Node* text_node = shadow_root->firstChild();
+ Selection().SetSelection(
+ SelectionInFlatTree::Builder()
+ .SetBaseAndExtent(PositionInFlatTree(text_node, 0),
+ PositionInFlatTree(text_node, 3))
+ .Build());
+ EXPECT_EQ_SELECTED_TEXT("hey");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ GetDocument().body()->focus(); // Move focus to document body.
+ EXPECT_EQ_SELECTED_TEXT("hey");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+}
+
+TEST_F(FrameSelectionTest, RangeInTextControl) {
+ SetBodyContent("<input id='field' value='hola'>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const field = GetDocument().getElementById("field");
+ field->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ Selection().SelectAll();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ field->blur();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+}
+
+// crbug.com/692898
+TEST_F(FrameSelectionTest, FocusingLinkHidesCaretInTextControl) {
+ SetBodyContent(
+ "<input id='field'>"
+ "<a href='www' id='alink'>link</a>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const field = GetDocument().getElementById("field");
+ field->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ Element* const alink = GetDocument().getElementById("alink");
+ alink->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+}
+
+// crbug.com/692898
+TEST_F(FrameSelectionTest, FocusingLinkHidesRangeInTextControl) {
+ SetBodyContent(
+ "<input id='field' value='hola'>"
+ "<a href='www' id='alink'>link</a>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const field = GetDocument().getElementById("field");
+ field->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ Selection().SelectAll();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ Element* const alink = GetDocument().getElementById("alink");
+ alink->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+}
+
+TEST_F(FrameSelectionTest, FocusingButtonHidesRangeInReadOnlyTextControl) {
+ SetBodyContent(
+ "<textarea readonly>Berlin</textarea>"
+ "<input type='submit' value='Submit'>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const textarea = GetDocument().QuerySelector("textarea");
+ textarea->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+
+ Selection().SelectAll();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ Element* const submit = GetDocument().QuerySelector("input");
+ submit->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+}
+
+TEST_F(FrameSelectionTest, FocusingButtonHidesRangeInDisabledTextControl) {
+ SetBodyContent(
+ "<textarea disabled>Berlin</textarea>"
+ "<input type='submit' value='Submit'>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const textarea = GetDocument().QuerySelector("textarea");
+ textarea->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+
+ // We use a double click to create the selection [Berlin].
+ // FrameSelection::SelectAll (= textarea.select() in JavaScript) would have
+ // been shorter, but currently that doesn't work on a *disabled* text control.
+ const IntRect elem_bounds = textarea->BoundsInViewport();
Xiaocheng 2017/05/08 22:08:29 I still prefer setting selection directly here. A
hugoh_UTC2 2017/05/09 09:22:45 I agree, but I think it is good to keep all tests
hugoh_UTC2 2017/05/09 09:42:30 (I think it is good to use mouse clicks here since
+ WebMouseEvent double_click(WebMouseEvent::kMouseDown, 0,
+ WebInputEvent::kTimeStampForTesting);
+ double_click.SetPositionInWidget(elem_bounds.X(), elem_bounds.Y());
+ double_click.SetPositionInScreen(elem_bounds.X(), elem_bounds.Y());
+ double_click.button = WebMouseEvent::Button::kLeft;
+ double_click.click_count = 2;
+ double_click.SetFrameScale(1);
+
+ GetFrame().GetEventHandler().HandleMousePressEvent(double_click);
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ Element* const submit = GetDocument().QuerySelector("input");
+ submit->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+}
+
+// crbug.com/713051
+TEST_F(FrameSelectionTest, FocusingNonEditableParentHidesCaretInTextControl) {
+ SetBodyContent(
+ "<div tabindex='-1' id='parent'>"
+ " <input id='field'>"
+ "</div>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const field = GetDocument().getElementById("field");
+ field->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ // Here the selection belongs to <input>'s shadow tree and that tree has a
+ // non-editable parent that is focused.
+ Element* const parent = GetDocument().getElementById("parent");
+ parent->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden()); // Focus is outside <input>
+ // so caret should not be visible.
+
+ parent->blur(); // Move focus to document body.
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden()); // Caret is still hidden.
+}
+
+// crbug.com/713051
+TEST_F(FrameSelectionTest, FocusingNonEditableParentHidesRangeInTextControl) {
+ SetBodyContent(
+ "<div tabindex='-1' id='parent'>"
+ " <input id='field' value='hola'>"
+ "</div>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const field = GetDocument().getElementById("field");
+ field->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ Selection().SelectAll();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ // Here the selection belongs to <input>'s shadow tree and that tree has a
+ // non-editable parent that is focused.
+ Element* const parent = GetDocument().getElementById("parent");
+ parent->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden()); // Focus is outside <input>
+ // so range should not be visible.
+
+ parent->blur(); // Move focus to document body.
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden()); // Range is still hidden.
+}
+
+TEST_F(FrameSelectionTest, CaretInFocusedEditableDiv) {
+ SetBodyContent("<div contenteditable id='ce'>blabla</div>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const ce = GetDocument().getElementById("ce");
+ ce->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ ce->blur(); // Move focus to document body.
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden()); // Caret is now hidden.
+}
+
+TEST_F(FrameSelectionTest, RangeInFocusedEditableDiv) {
+ SetBodyContent("<div contenteditable id='ce'>blabla</div>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const ce = GetDocument().getElementById("ce");
+ ce->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ Selection().SelectAll();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ ce->blur(); // Move focus to document body.
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden()); // Range is still visible.
+}
+
+TEST_F(FrameSelectionTest, FocusingLinkHidesCaretInContentEditable) {
+ SetBodyContent(
+ "<div contenteditable id='ce'>blabla</div>"
+ "<a href='www' id='alink'>link</a>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const ce = GetDocument().getElementById("ce");
+ ce->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ Element* const alink = GetDocument().getElementById("alink");
+ alink->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+}
+
+TEST_F(FrameSelectionTest, FocusingLinkKeepsRangeInContentEditable) {
+ SetBodyContent(
+ "<div contenteditable id='ce'>blabla</div>"
+ "<a href='www' id='alink'>link</a>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const ce = GetDocument().getElementById("ce");
+ ce->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ Selection().SelectAll();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ Element* const alink = GetDocument().getElementById("alink");
+ alink->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+}
+
+TEST_F(FrameSelectionTest, FocusingEditableParentKeepsEditableCaret) {
+ SetBodyContent(
+ "<div contenteditable tabindex='-1' id='parent'>"
+ "<div contenteditable id='ce'>blabla</div>"
+ "</div>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ // TODO(editing-dev): Blink should be able to focus the inner <div>.
+ // Element* const ce = GetDocument().getElementById("ce");
+ // ce->focus();
+ // EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ // EXPECT_FALSE(Selection().IsHidden());
+
+ Element* const parent = GetDocument().getElementById("parent");
+ parent->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden()); // Focus is within editing boundary,
+ // caret should be visible.
+
+ parent->blur(); // Move focus to document body.
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden()); // Focus is outside editing boundary
+ // so caret should be hidden.
+}
+
+TEST_F(FrameSelectionTest, FocusingEditableParentKeepsEditableRange) {
+ SetBodyContent(
+ "<div contenteditable tabindex='-1' id='parent'>"
+ "<div contenteditable id='ce'>blabla</div>"
+ "</div>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ // TODO(editing-dev): Blink should be able to focus the inner <div>.
+ // Element* const ce = GetDocument().getElementById("ce");
+ // ce->focus();
+ // EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ // EXPECT_FALSE(Selection().IsHidden());
+
+ // Selection().SelectAll();
+ // EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ // EXPECT_FALSE(Selection().IsHidden());
+
+ Element* const parent = GetDocument().getElementById("parent");
+ parent->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden()); // Focus is within editing boundary,
+ // range should be visible.
+
+ Selection().SelectAll();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ parent->blur(); // Move focus to document body.
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden()); // Focus is outside editing boundary
+ // but range should still be visible.
+}
+
+TEST_F(FrameSelectionTest, FocusingNonEditableParentHidesEditableCaret) {
+ SetBodyContent(
+ "<div tabindex='-1' id='parent'>"
+ "<div contenteditable id='ce'>blabla</div>"
+ "</div>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const ce = GetDocument().getElementById("ce");
+ ce->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ // Here the selection belongs to <div>'s shadow tree and that tree has a
+ // non-editable parent that is focused.
+ Element* const parent = GetDocument().getElementById("parent");
+ parent->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden()); // Focus is outside editing boundary
+ // so caret should be hidden.
+
+ parent->blur(); // Move focus to document body.
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden()); // Caret is still hidden.
+}
+
+TEST_F(FrameSelectionTest, FocusingNonEditableParentKeepsEditableRange) {
+ SetBodyContent(
+ "<div tabindex='-1' id='parent'>"
+ "<div contenteditable id='ce'>blabla</div>"
+ "</div>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const ce = GetDocument().getElementById("ce");
+ ce->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ Selection().SelectAll();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ // Here the selection belongs to <div>'s shadow tree and that tree has a
+ // non-editable parent that is focused.
+ Element* const parent = GetDocument().getElementById("parent");
+ parent->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden()); // Focus is outside editing boundary
+ // but range should still be visible.
+
+ parent->blur(); // Move focus to document body.
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden()); // Range is still visible.
+}
+
+// crbug.com/707143
+TEST_F(FrameSelectionTest, RangeContainsFocus) {
+ SetBodyContent(
+ "<div>"
+ " <div>"
+ " <span id='start'>start</span>"
+ " </div>"
+ " <a href='www' id='alink'>link</a>"
+ " <div>line 1</div>"
+ " <div>line 2</div>"
+ " <div>line 3</div>"
+ " <div>line 4</div>"
+ " <span id='end'>end</span>"
+ " <div></div>"
+ "</div>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const start = GetDocument().getElementById("start");
+ Element* const end = GetDocument().getElementById("end");
+ Selection().SetSelection(
+ SelectionInDOMTree::Builder()
+ .SetBaseAndExtent(Position(start, 0), Position(end, 3))
+ .Build());
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ Element* const alink = GetDocument().getElementById("alink");
+ alink->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden()); // Range still visible.
+}
+
+// crbug.com/707143
+TEST_F(FrameSelectionTest, RangeOutsideFocus) {
+ // Here the selection sits on a sub tree that hasn't the focused element.
+ // This test case is the reason why we separate FrameSelection::HasFocus() and
+ // FrameSelection::IsHidden(). Even when the selection's DOM nodes are
+ // completely disconnected from the focused node, we still want the selection
+ // to be visible (not hidden).
+ SetBodyContent(
+ "<a href='www' id='alink'>link</a>"
+ "<div>"
+ " <div>"
+ " <span id='start'>start</span>"
+ " </div>"
+ " <div>line 1</div>"
+ " <div>line 2</div>"
+ " <div>line 3</div>"
+ " <div>line 4</div>"
+ " <span id='end'>end</span>"
+ " <div></div>"
+ "</div>");
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_TRUE(Selection().IsHidden());
+
+ Element* const start = GetDocument().getElementById("start");
+ Element* const end = GetDocument().getElementById("end");
+ Selection().SetSelection(
+ SelectionInDOMTree::Builder()
+ .SetBaseAndExtent(Position(start, 0), Position(end, 3))
+ .Build());
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_TRUE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden());
+
+ Element* const alink = GetDocument().getElementById("alink");
+ alink->focus();
+ EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
+ EXPECT_FALSE(Selection().SelectionHasFocus());
+ EXPECT_FALSE(Selection().IsHidden()); // Range still visible.
+}
+
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698