OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/editing/FrameSelection.h" | 5 #include "core/editing/FrameSelection.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include "bindings/core/v8/ExceptionState.h" | 8 #include "bindings/core/v8/ExceptionState.h" |
9 #include "core/dom/Document.h" | 9 #include "core/dom/Document.h" |
10 #include "core/dom/Element.h" | 10 #include "core/dom/Element.h" |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
342 .Build()); | 342 .Build()); |
343 // Should not crash inside. | 343 // Should not crash inside. |
344 const VisibleSelectionInFlatTree& selection = | 344 const VisibleSelectionInFlatTree& selection = |
345 Selection().ComputeVisibleSelectionInFlatTree(); | 345 Selection().ComputeVisibleSelectionInFlatTree(); |
346 | 346 |
347 // This only records the current behavior. It might be changed in the future. | 347 // This only records the current behavior. It might be changed in the future. |
348 EXPECT_EQ(PositionInFlatTree(foo, 0), selection.Base()); | 348 EXPECT_EQ(PositionInFlatTree(foo, 0), selection.Base()); |
349 EXPECT_EQ(PositionInFlatTree(foo, 0), selection.Extent()); | 349 EXPECT_EQ(PositionInFlatTree(foo, 0), selection.Extent()); |
350 } | 350 } |
351 | 351 |
352 TEST_F(FrameSelectionTest, CaretInShadowTree) { | |
353 SetBodyContent("<p id=host></p>bar"); | |
354 ShadowRoot* shadow_root = | |
355 SetShadowContent("<div contenteditable id='ce'>foo</div>", "host"); | |
356 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
357 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
358 EXPECT_TRUE(Selection().IsHidden()); | |
359 | |
360 Element* const ce = shadow_root->getElementById("ce"); | |
361 ce->focus(); | |
362 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
363 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
364 EXPECT_FALSE(Selection().IsHidden()); | |
365 | |
366 ce->blur(); // Move focus to document body. | |
367 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
368 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
369 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
| |
370 } | |
371 | |
372 TEST_F(FrameSelectionTest, CaretInTextControl) { | |
373 SetBodyContent("<input id='field'>"); // <input> hosts a shadow tree. | |
374 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
375 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
376 EXPECT_TRUE(Selection().IsHidden()); | |
377 | |
378 Element* const field = GetDocument().getElementById("field"); | |
379 field->focus(); | |
380 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
381 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
382 EXPECT_FALSE(Selection().IsHidden()); | |
383 | |
384 field->blur(); // Move focus to document body. | |
385 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
386 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
387 EXPECT_TRUE(Selection().IsHidden()); // Caret is now hidden. | |
388 } | |
389 | |
390 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.
| |
391 SetBodyContent("<p id='host'></p>"); | |
392 ShadowRoot* shadow_root = SetShadowContent("hey", "host"); | |
393 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
394 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
395 EXPECT_TRUE(Selection().IsHidden()); | |
396 | |
397 Node* text_node = shadow_root->firstChild(); | |
398 Selection().SetSelection( | |
399 SelectionInFlatTree::Builder() | |
400 .SetBaseAndExtent(PositionInFlatTree(text_node, 0), | |
401 PositionInFlatTree(text_node, 3)) | |
402 .Build()); | |
403 EXPECT_EQ_SELECTED_TEXT("hey"); | |
404 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
405 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
406 EXPECT_FALSE(Selection().IsHidden()); | |
407 | |
408 GetDocument().body()->focus(); // Move focus to document body. | |
409 EXPECT_EQ_SELECTED_TEXT("hey"); | |
410 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
411 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
412 EXPECT_FALSE(Selection().IsHidden()); | |
413 } | |
414 | |
415 TEST_F(FrameSelectionTest, RangeInTextControl) { | |
416 SetBodyContent("<input id='field' value='hola'>"); | |
417 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
418 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
419 EXPECT_TRUE(Selection().IsHidden()); | |
420 | |
421 Element* const field = GetDocument().getElementById("field"); | |
422 field->focus(); | |
423 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
424 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
425 EXPECT_FALSE(Selection().IsHidden()); | |
426 | |
427 Selection().SelectAll(); | |
428 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
429 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
430 EXPECT_FALSE(Selection().IsHidden()); | |
431 | |
432 field->blur(); | |
433 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
434 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
435 EXPECT_TRUE(Selection().IsHidden()); | |
436 } | |
437 | |
438 // crbug.com/692898 | |
439 TEST_F(FrameSelectionTest, FocusingLinkHidesCaretInTextControl) { | |
440 SetBodyContent( | |
441 "<input id='field'>" | |
442 "<a href='www' id='alink'>link</a>"); | |
443 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
444 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
445 EXPECT_TRUE(Selection().IsHidden()); | |
446 | |
447 Element* const field = GetDocument().getElementById("field"); | |
448 field->focus(); | |
449 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
450 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
451 EXPECT_FALSE(Selection().IsHidden()); | |
452 | |
453 Element* const alink = GetDocument().getElementById("alink"); | |
454 alink->focus(); | |
455 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
456 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
457 EXPECT_TRUE(Selection().IsHidden()); | |
458 } | |
459 | |
460 // crbug.com/692898 | |
461 TEST_F(FrameSelectionTest, FocusingLinkHidesRangeInTextControl) { | |
462 SetBodyContent( | |
463 "<input id='field' value='hola'>" | |
464 "<a href='www' id='alink'>link</a>"); | |
465 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
466 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
467 EXPECT_TRUE(Selection().IsHidden()); | |
468 | |
469 Element* const field = GetDocument().getElementById("field"); | |
470 field->focus(); | |
471 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
472 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
473 EXPECT_FALSE(Selection().IsHidden()); | |
474 | |
475 Selection().SelectAll(); | |
476 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
477 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
478 EXPECT_FALSE(Selection().IsHidden()); | |
479 | |
480 Element* const alink = GetDocument().getElementById("alink"); | |
481 alink->focus(); | |
482 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
483 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
484 EXPECT_TRUE(Selection().IsHidden()); | |
485 } | |
486 | |
487 TEST_F(FrameSelectionTest, FocusingButtonHidesRangeInReadOnlyTextControl) { | |
488 SetBodyContent( | |
489 "<textarea readonly>Berlin</textarea>" | |
490 "<input type='submit' value='Submit'>"); | |
491 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
492 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
493 EXPECT_TRUE(Selection().IsHidden()); | |
494 | |
495 Element* const textarea = GetDocument().QuerySelector("textarea"); | |
496 textarea->focus(); | |
497 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
498 | |
499 Selection().SelectAll(); | |
500 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
501 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
502 EXPECT_FALSE(Selection().IsHidden()); | |
503 | |
504 Element* const submit = GetDocument().QuerySelector("input"); | |
505 submit->focus(); | |
506 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
507 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
508 EXPECT_TRUE(Selection().IsHidden()); | |
509 } | |
510 | |
511 TEST_F(FrameSelectionTest, FocusingButtonHidesRangeInDisabledTextControl) { | |
512 SetBodyContent( | |
513 "<textarea disabled>Berlin</textarea>" | |
514 "<input type='submit' value='Submit'>"); | |
515 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
516 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
517 EXPECT_TRUE(Selection().IsHidden()); | |
518 | |
519 Element* const textarea = GetDocument().QuerySelector("textarea"); | |
520 textarea->focus(); | |
521 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
522 | |
523 // We use a double click to create the selection [Berlin]. | |
524 // FrameSelection::SelectAll (= textarea.select() in JavaScript) would have | |
525 // been shorter, but currently that doesn't work on a *disabled* text control. | |
526 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
| |
527 WebMouseEvent double_click(WebMouseEvent::kMouseDown, 0, | |
528 WebInputEvent::kTimeStampForTesting); | |
529 double_click.SetPositionInWidget(elem_bounds.X(), elem_bounds.Y()); | |
530 double_click.SetPositionInScreen(elem_bounds.X(), elem_bounds.Y()); | |
531 double_click.button = WebMouseEvent::Button::kLeft; | |
532 double_click.click_count = 2; | |
533 double_click.SetFrameScale(1); | |
534 | |
535 GetFrame().GetEventHandler().HandleMousePressEvent(double_click); | |
536 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
537 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
538 EXPECT_FALSE(Selection().IsHidden()); | |
539 | |
540 Element* const submit = GetDocument().QuerySelector("input"); | |
541 submit->focus(); | |
542 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
543 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
544 EXPECT_TRUE(Selection().IsHidden()); | |
545 } | |
546 | |
547 // crbug.com/713051 | |
548 TEST_F(FrameSelectionTest, FocusingNonEditableParentHidesCaretInTextControl) { | |
549 SetBodyContent( | |
550 "<div tabindex='-1' id='parent'>" | |
551 " <input id='field'>" | |
552 "</div>"); | |
553 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
554 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
555 EXPECT_TRUE(Selection().IsHidden()); | |
556 | |
557 Element* const field = GetDocument().getElementById("field"); | |
558 field->focus(); | |
559 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
560 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
561 EXPECT_FALSE(Selection().IsHidden()); | |
562 | |
563 // Here the selection belongs to <input>'s shadow tree and that tree has a | |
564 // non-editable parent that is focused. | |
565 Element* const parent = GetDocument().getElementById("parent"); | |
566 parent->focus(); | |
567 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
568 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
569 EXPECT_TRUE(Selection().IsHidden()); // Focus is outside <input> | |
570 // so caret should not be visible. | |
571 | |
572 parent->blur(); // Move focus to document body. | |
573 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
574 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
575 EXPECT_TRUE(Selection().IsHidden()); // Caret is still hidden. | |
576 } | |
577 | |
578 // crbug.com/713051 | |
579 TEST_F(FrameSelectionTest, FocusingNonEditableParentHidesRangeInTextControl) { | |
580 SetBodyContent( | |
581 "<div tabindex='-1' id='parent'>" | |
582 " <input id='field' value='hola'>" | |
583 "</div>"); | |
584 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
585 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
586 EXPECT_TRUE(Selection().IsHidden()); | |
587 | |
588 Element* const field = GetDocument().getElementById("field"); | |
589 field->focus(); | |
590 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
591 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
592 EXPECT_FALSE(Selection().IsHidden()); | |
593 | |
594 Selection().SelectAll(); | |
595 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
596 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
597 EXPECT_FALSE(Selection().IsHidden()); | |
598 | |
599 // Here the selection belongs to <input>'s shadow tree and that tree has a | |
600 // non-editable parent that is focused. | |
601 Element* const parent = GetDocument().getElementById("parent"); | |
602 parent->focus(); | |
603 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
604 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
605 EXPECT_TRUE(Selection().IsHidden()); // Focus is outside <input> | |
606 // so range should not be visible. | |
607 | |
608 parent->blur(); // Move focus to document body. | |
609 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
610 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
611 EXPECT_TRUE(Selection().IsHidden()); // Range is still hidden. | |
612 } | |
613 | |
614 TEST_F(FrameSelectionTest, CaretInFocusedEditableDiv) { | |
615 SetBodyContent("<div contenteditable id='ce'>blabla</div>"); | |
616 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
617 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
618 EXPECT_TRUE(Selection().IsHidden()); | |
619 | |
620 Element* const ce = GetDocument().getElementById("ce"); | |
621 ce->focus(); | |
622 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
623 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
624 EXPECT_FALSE(Selection().IsHidden()); | |
625 | |
626 ce->blur(); // Move focus to document body. | |
627 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
628 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
629 EXPECT_TRUE(Selection().IsHidden()); // Caret is now hidden. | |
630 } | |
631 | |
632 TEST_F(FrameSelectionTest, RangeInFocusedEditableDiv) { | |
633 SetBodyContent("<div contenteditable id='ce'>blabla</div>"); | |
634 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
635 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
636 EXPECT_TRUE(Selection().IsHidden()); | |
637 | |
638 Element* const ce = GetDocument().getElementById("ce"); | |
639 ce->focus(); | |
640 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
641 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
642 EXPECT_FALSE(Selection().IsHidden()); | |
643 | |
644 Selection().SelectAll(); | |
645 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
646 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
647 EXPECT_FALSE(Selection().IsHidden()); | |
648 | |
649 ce->blur(); // Move focus to document body. | |
650 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
651 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
652 EXPECT_FALSE(Selection().IsHidden()); // Range is still visible. | |
653 } | |
654 | |
655 TEST_F(FrameSelectionTest, FocusingLinkHidesCaretInContentEditable) { | |
656 SetBodyContent( | |
657 "<div contenteditable id='ce'>blabla</div>" | |
658 "<a href='www' id='alink'>link</a>"); | |
659 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
660 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
661 EXPECT_TRUE(Selection().IsHidden()); | |
662 | |
663 Element* const ce = GetDocument().getElementById("ce"); | |
664 ce->focus(); | |
665 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
666 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
667 EXPECT_FALSE(Selection().IsHidden()); | |
668 | |
669 Element* const alink = GetDocument().getElementById("alink"); | |
670 alink->focus(); | |
671 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
672 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
673 EXPECT_TRUE(Selection().IsHidden()); | |
674 } | |
675 | |
676 TEST_F(FrameSelectionTest, FocusingLinkKeepsRangeInContentEditable) { | |
677 SetBodyContent( | |
678 "<div contenteditable id='ce'>blabla</div>" | |
679 "<a href='www' id='alink'>link</a>"); | |
680 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
681 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
682 EXPECT_TRUE(Selection().IsHidden()); | |
683 | |
684 Element* const ce = GetDocument().getElementById("ce"); | |
685 ce->focus(); | |
686 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
687 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
688 EXPECT_FALSE(Selection().IsHidden()); | |
689 | |
690 Selection().SelectAll(); | |
691 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
692 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
693 EXPECT_FALSE(Selection().IsHidden()); | |
694 | |
695 Element* const alink = GetDocument().getElementById("alink"); | |
696 alink->focus(); | |
697 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
698 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
699 EXPECT_FALSE(Selection().IsHidden()); | |
700 } | |
701 | |
702 TEST_F(FrameSelectionTest, FocusingEditableParentKeepsEditableCaret) { | |
703 SetBodyContent( | |
704 "<div contenteditable tabindex='-1' id='parent'>" | |
705 "<div contenteditable id='ce'>blabla</div>" | |
706 "</div>"); | |
707 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
708 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
709 EXPECT_TRUE(Selection().IsHidden()); | |
710 | |
711 // TODO(editing-dev): Blink should be able to focus the inner <div>. | |
712 // Element* const ce = GetDocument().getElementById("ce"); | |
713 // ce->focus(); | |
714 // EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
715 // EXPECT_FALSE(Selection().IsHidden()); | |
716 | |
717 Element* const parent = GetDocument().getElementById("parent"); | |
718 parent->focus(); | |
719 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
720 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
721 EXPECT_FALSE(Selection().IsHidden()); // Focus is within editing boundary, | |
722 // caret should be visible. | |
723 | |
724 parent->blur(); // Move focus to document body. | |
725 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
726 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
727 EXPECT_TRUE(Selection().IsHidden()); // Focus is outside editing boundary | |
728 // so caret should be hidden. | |
729 } | |
730 | |
731 TEST_F(FrameSelectionTest, FocusingEditableParentKeepsEditableRange) { | |
732 SetBodyContent( | |
733 "<div contenteditable tabindex='-1' id='parent'>" | |
734 "<div contenteditable id='ce'>blabla</div>" | |
735 "</div>"); | |
736 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
737 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
738 EXPECT_TRUE(Selection().IsHidden()); | |
739 | |
740 // TODO(editing-dev): Blink should be able to focus the inner <div>. | |
741 // Element* const ce = GetDocument().getElementById("ce"); | |
742 // ce->focus(); | |
743 // EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
744 // EXPECT_FALSE(Selection().IsHidden()); | |
745 | |
746 // Selection().SelectAll(); | |
747 // EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
748 // EXPECT_FALSE(Selection().IsHidden()); | |
749 | |
750 Element* const parent = GetDocument().getElementById("parent"); | |
751 parent->focus(); | |
752 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
753 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
754 EXPECT_FALSE(Selection().IsHidden()); // Focus is within editing boundary, | |
755 // range should be visible. | |
756 | |
757 Selection().SelectAll(); | |
758 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
759 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
760 EXPECT_FALSE(Selection().IsHidden()); | |
761 | |
762 parent->blur(); // Move focus to document body. | |
763 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
764 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
765 EXPECT_FALSE(Selection().IsHidden()); // Focus is outside editing boundary | |
766 // but range should still be visible. | |
767 } | |
768 | |
769 TEST_F(FrameSelectionTest, FocusingNonEditableParentHidesEditableCaret) { | |
770 SetBodyContent( | |
771 "<div tabindex='-1' id='parent'>" | |
772 "<div contenteditable id='ce'>blabla</div>" | |
773 "</div>"); | |
774 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
775 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
776 EXPECT_TRUE(Selection().IsHidden()); | |
777 | |
778 Element* const ce = GetDocument().getElementById("ce"); | |
779 ce->focus(); | |
780 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
781 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
782 EXPECT_FALSE(Selection().IsHidden()); | |
783 | |
784 // Here the selection belongs to <div>'s shadow tree and that tree has a | |
785 // non-editable parent that is focused. | |
786 Element* const parent = GetDocument().getElementById("parent"); | |
787 parent->focus(); | |
788 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
789 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
790 EXPECT_TRUE(Selection().IsHidden()); // Focus is outside editing boundary | |
791 // so caret should be hidden. | |
792 | |
793 parent->blur(); // Move focus to document body. | |
794 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
795 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
796 EXPECT_TRUE(Selection().IsHidden()); // Caret is still hidden. | |
797 } | |
798 | |
799 TEST_F(FrameSelectionTest, FocusingNonEditableParentKeepsEditableRange) { | |
800 SetBodyContent( | |
801 "<div tabindex='-1' id='parent'>" | |
802 "<div contenteditable id='ce'>blabla</div>" | |
803 "</div>"); | |
804 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
805 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
806 EXPECT_TRUE(Selection().IsHidden()); | |
807 | |
808 Element* const ce = GetDocument().getElementById("ce"); | |
809 ce->focus(); | |
810 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret()); | |
811 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
812 EXPECT_FALSE(Selection().IsHidden()); | |
813 | |
814 Selection().SelectAll(); | |
815 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
816 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
817 EXPECT_FALSE(Selection().IsHidden()); | |
818 | |
819 // Here the selection belongs to <div>'s shadow tree and that tree has a | |
820 // non-editable parent that is focused. | |
821 Element* const parent = GetDocument().getElementById("parent"); | |
822 parent->focus(); | |
823 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
824 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
825 EXPECT_FALSE(Selection().IsHidden()); // Focus is outside editing boundary | |
826 // but range should still be visible. | |
827 | |
828 parent->blur(); // Move focus to document body. | |
829 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
830 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
831 EXPECT_FALSE(Selection().IsHidden()); // Range is still visible. | |
832 } | |
833 | |
834 // crbug.com/707143 | |
835 TEST_F(FrameSelectionTest, RangeContainsFocus) { | |
836 SetBodyContent( | |
837 "<div>" | |
838 " <div>" | |
839 " <span id='start'>start</span>" | |
840 " </div>" | |
841 " <a href='www' id='alink'>link</a>" | |
842 " <div>line 1</div>" | |
843 " <div>line 2</div>" | |
844 " <div>line 3</div>" | |
845 " <div>line 4</div>" | |
846 " <span id='end'>end</span>" | |
847 " <div></div>" | |
848 "</div>"); | |
849 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
850 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
851 EXPECT_TRUE(Selection().IsHidden()); | |
852 | |
853 Element* const start = GetDocument().getElementById("start"); | |
854 Element* const end = GetDocument().getElementById("end"); | |
855 Selection().SetSelection( | |
856 SelectionInDOMTree::Builder() | |
857 .SetBaseAndExtent(Position(start, 0), Position(end, 3)) | |
858 .Build()); | |
859 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
860 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
861 EXPECT_FALSE(Selection().IsHidden()); | |
862 | |
863 Element* const alink = GetDocument().getElementById("alink"); | |
864 alink->focus(); | |
865 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
866 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
867 EXPECT_FALSE(Selection().IsHidden()); // Range still visible. | |
868 } | |
869 | |
870 // crbug.com/707143 | |
871 TEST_F(FrameSelectionTest, RangeOutsideFocus) { | |
872 // Here the selection sits on a sub tree that hasn't the focused element. | |
873 // This test case is the reason why we separate FrameSelection::HasFocus() and | |
874 // FrameSelection::IsHidden(). Even when the selection's DOM nodes are | |
875 // completely disconnected from the focused node, we still want the selection | |
876 // to be visible (not hidden). | |
877 SetBodyContent( | |
878 "<a href='www' id='alink'>link</a>" | |
879 "<div>" | |
880 " <div>" | |
881 " <span id='start'>start</span>" | |
882 " </div>" | |
883 " <div>line 1</div>" | |
884 " <div>line 2</div>" | |
885 " <div>line 3</div>" | |
886 " <div>line 4</div>" | |
887 " <span id='end'>end</span>" | |
888 " <div></div>" | |
889 "</div>"); | |
890 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone()); | |
891 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
892 EXPECT_TRUE(Selection().IsHidden()); | |
893 | |
894 Element* const start = GetDocument().getElementById("start"); | |
895 Element* const end = GetDocument().getElementById("end"); | |
896 Selection().SetSelection( | |
897 SelectionInDOMTree::Builder() | |
898 .SetBaseAndExtent(Position(start, 0), Position(end, 3)) | |
899 .Build()); | |
900 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
901 EXPECT_TRUE(Selection().SelectionHasFocus()); | |
902 EXPECT_FALSE(Selection().IsHidden()); | |
903 | |
904 Element* const alink = GetDocument().getElementById("alink"); | |
905 alink->focus(); | |
906 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange()); | |
907 EXPECT_FALSE(Selection().SelectionHasFocus()); | |
908 EXPECT_FALSE(Selection().IsHidden()); // Range still visible. | |
909 } | |
910 | |
352 } // namespace blink | 911 } // namespace blink |
OLD | NEW |