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

Side by Side 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: Rebase + cosmetic changes 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 unified diff | Download patch
OLDNEW
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
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("<input id='field'>"); // <input> hosts a shadow tree.
354 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
355 EXPECT_FALSE(Selection().IsActive());
356
357 Element* const field = GetDocument().getElementById("field");
358 field->focus();
359 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
360 EXPECT_TRUE(Selection().IsActive());
361
362 field->blur(); // Move focus to document body.
363 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
364 EXPECT_FALSE(Selection().IsActive()); // Caret is now hidden.
365 }
366
367 TEST_F(FrameSelectionTest, RangeInShadowTree) {
368 SetBodyContent("<input id='field' value='hola'>");
369 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
370 EXPECT_FALSE(Selection().IsActive());
371
372 Element* const field = GetDocument().getElementById("field");
373 field->focus();
374 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
375 EXPECT_TRUE(Selection().IsActive());
376
377 Selection().SelectAll();
378 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
379 EXPECT_TRUE(Selection().IsActive());
380
381 field->blur(); // Move focus to document body.
382 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
383 EXPECT_FALSE(Selection().IsActive()); // Range is now hidden.
384 }
385
386 // crbug.com/692898
387 TEST_F(FrameSelectionTest, FocusingLinkHidesCaretInTextControl) {
388 SetBodyContent(
389 "<input id='field'>"
390 "<a href='www' id='alink'>link</a>");
391 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
392 EXPECT_FALSE(Selection().IsActive());
393
394 Element* const field = GetDocument().getElementById("field");
395 field->focus();
396 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
397 EXPECT_TRUE(Selection().IsActive());
398
399 Element* const alink = GetDocument().getElementById("alink");
400 alink->focus();
401 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
402 EXPECT_FALSE(Selection().IsActive());
403 }
404
405 // crbug.com/692898
406 TEST_F(FrameSelectionTest, FocusingLinkHidesRangeInTextControl) {
407 SetBodyContent(
408 "<input id='field' value='hola'>"
409 "<a href='www' id='alink'>link</a>");
410 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
411 EXPECT_FALSE(Selection().IsActive());
412
413 Element* const field = GetDocument().getElementById("field");
414 field->focus();
415 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
416 EXPECT_TRUE(Selection().IsActive());
417
418 Selection().SelectAll();
419 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
420 EXPECT_TRUE(Selection().IsActive());
421
422 Element* const alink = GetDocument().getElementById("alink");
423 alink->focus();
424 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
425 EXPECT_FALSE(Selection().IsActive());
426 }
427
428 // crbug.com/713051
429 TEST_F(FrameSelectionTest, FocusingNonEditableParentHidesCaretInTextControl) {
430 SetBodyContent(
431 "<div tabindex='-1' id='parent'>"
432 " <input id='field'>"
433 "</div>");
434 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
435 EXPECT_FALSE(Selection().IsActive());
436
437 Element* const field = GetDocument().getElementById("field");
438 field->focus();
439 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
440 EXPECT_TRUE(Selection().IsActive());
441
442 // Here the selection belongs to <input>'s shadow tree and that tree has a
443 // non-editable parent that is focused.
444 Element* const parent = GetDocument().getElementById("parent");
445 parent->focus();
446 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
447 EXPECT_FALSE(Selection().IsActive()); // Focus is outside <input>
448 // so caret should not be visible.
449
450 parent->blur(); // Move focus to document body.
451 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
452 EXPECT_FALSE(Selection().IsActive()); // Caret is still hidden.
453 }
454
455 // crbug.com/713051
456 TEST_F(FrameSelectionTest, FocusingNonEditableParentHidesRangeInTextControl) {
457 SetBodyContent(
458 "<div tabindex='-1' id='parent'>"
459 " <input id='field' value='hola'>"
460 "</div>");
461 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
462 EXPECT_FALSE(Selection().IsActive());
463
464 Element* const field = GetDocument().getElementById("field");
465 field->focus();
466 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
467 EXPECT_TRUE(Selection().IsActive());
468
469 Selection().SelectAll();
470 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
471 EXPECT_TRUE(Selection().IsActive());
472
473 // Here the selection belongs to <input>'s shadow tree and that tree has a
474 // non-editable parent that is focused.
475 Element* const parent = GetDocument().getElementById("parent");
476 parent->focus();
477 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
478 EXPECT_FALSE(Selection().IsActive()); // Focus is outside <input>
479 // so range should not be visible.
480
481 parent->blur(); // Move focus to document body.
482 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
483 EXPECT_FALSE(Selection().IsActive()); // Range is still hidden.
484 }
485
486 TEST_F(FrameSelectionTest, CaretInFocusedEditableDiv) {
487 SetBodyContent("<div contenteditable id='ce'>blabla</div>");
488 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
489 EXPECT_FALSE(Selection().IsActive());
490
491 Element* const ce = GetDocument().getElementById("ce");
492 ce->focus();
493 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
494 EXPECT_TRUE(Selection().IsActive());
495
496 ce->blur(); // Move focus to document body.
497 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
498 EXPECT_FALSE(Selection().IsActive()); // Caret is now hidden.
499 }
500
501 TEST_F(FrameSelectionTest, RangeInFocusedEditableDiv) {
502 SetBodyContent("<div contenteditable id='ce'>blabla</div>");
503 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
504 EXPECT_FALSE(Selection().IsActive());
505
506 Element* const ce = GetDocument().getElementById("ce");
507 ce->focus();
508 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
509 EXPECT_TRUE(Selection().IsActive());
510
511 Selection().SelectAll();
512 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
513 EXPECT_TRUE(Selection().IsActive());
514
515 ce->blur(); // Move focus to document body.
516 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
517 EXPECT_TRUE(Selection().IsActive()); // Range is still visible.
518 }
519
520 TEST_F(FrameSelectionTest, FocusingLinkHidesCaretInContentEditable) {
521 SetBodyContent(
522 "<div contenteditable id='ce'>blabla</div>"
523 "<a href='www' id='alink'>link</a>");
524 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
525 EXPECT_FALSE(Selection().IsActive());
526
527 Element* const ce = GetDocument().getElementById("ce");
528 ce->focus();
529 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
530 EXPECT_TRUE(Selection().IsActive());
531
532 Element* const alink = GetDocument().getElementById("alink");
533 alink->focus();
534 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
535 EXPECT_FALSE(Selection().IsActive());
536 }
537
538 TEST_F(FrameSelectionTest, FocusingLinkKeepsRangeInContentEditable) {
539 SetBodyContent(
540 "<div contenteditable id='ce'>blabla</div>"
541 "<a href='www' id='alink'>link</a>");
542 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
543 EXPECT_FALSE(Selection().IsActive());
544
545 Element* const ce = GetDocument().getElementById("ce");
546 ce->focus();
547 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
548 EXPECT_TRUE(Selection().IsActive());
549
550 Selection().SelectAll();
551 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
552 EXPECT_TRUE(Selection().IsActive());
553
554 Element* const alink = GetDocument().getElementById("alink");
555 alink->focus();
556 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
557 EXPECT_TRUE(Selection().IsActive());
558 }
559
560 TEST_F(FrameSelectionTest, FocusingEditableParentKeepsEditableCaret) {
561 SetBodyContent(
562 "<div contenteditable tabindex='-1' id='parent'>"
563 "<div contenteditable id='ce'>blabla</div>"
564 "</div>");
565 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
566 EXPECT_FALSE(Selection().IsActive());
567
568 // TODO(editing-dev): Blink should be able to focus the inner <div>.
569 // Element* const ce = GetDocument().getElementById("ce");
570 // ce->focus();
571 // EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
572 // EXPECT_TRUE(Selection().IsActive());
573
574 Element* const parent = GetDocument().getElementById("parent");
575 parent->focus();
576 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
577 EXPECT_TRUE(Selection().IsActive()); // Focus is within editing boundary,
578 // caret should be visible.
579
580 parent->blur(); // Move focus to document body.
581 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
582 EXPECT_FALSE(Selection().IsActive()); // Focus is outside editing boundary
583 // so caret should be hidden.
584 }
585
586 TEST_F(FrameSelectionTest, FocusingEditableParentKeepsEditableRange) {
587 SetBodyContent(
588 "<div contenteditable tabindex='-1' id='parent'>"
589 "<div contenteditable id='ce'>blabla</div>"
590 "</div>");
591 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
592 EXPECT_FALSE(Selection().IsActive());
593
594 // TODO(editing-dev): Blink should be able to focus the inner <div>.
595 // Element* const ce = GetDocument().getElementById("ce");
596 // ce->focus();
597 // EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
598 // EXPECT_TRUE(Selection().IsActive());
599
600 // Selection().SelectAll();
601 // EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
602 // EXPECT_TRUE(Selection().IsActive());
603
604 Element* const parent = GetDocument().getElementById("parent");
605 parent->focus();
606 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
607 EXPECT_TRUE(Selection().IsActive()); // Focus is within editing boundary,
608 // range should be visible.
609
610 Selection().SelectAll();
611 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
612 EXPECT_TRUE(Selection().IsActive());
613
614 parent->blur(); // Move focus to document body.
615 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
616 EXPECT_TRUE(Selection().IsActive()); // Focus is outside editing boundary
617 // but range should still be visible.
618 }
619
620 TEST_F(FrameSelectionTest, FocusingNonEditableParentHidesEditableCaret) {
621 SetBodyContent(
622 "<div tabindex='-1' id='parent'>"
623 "<div contenteditable id='ce'>blabla</div>"
624 "</div>");
625 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
626 EXPECT_FALSE(Selection().IsActive());
627
628 Element* const ce = GetDocument().getElementById("ce");
629 ce->focus();
630 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
631 EXPECT_TRUE(Selection().IsActive());
632
633 // Here the selection belongs to <divs>'s shadow tree and that tree has a
634 // non-editable parent that is focused.
635 Element* const parent = GetDocument().getElementById("parent");
636 parent->focus();
637 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
638 EXPECT_FALSE(Selection().IsActive()); // Focus is outside editing boundary
639 // so caret should be hidden.
640
641 parent->blur(); // Move focus to document body.
642 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
643 EXPECT_FALSE(Selection().IsActive()); // Caret is still hidden.
644 }
645
646 TEST_F(FrameSelectionTest, FocusingNonEditableParentKeepsEditableRange) {
647 SetBodyContent(
648 "<div tabindex='-1' id='parent'>"
649 "<div contenteditable id='ce'>blabla</div>"
650 "</div>");
651 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
652 EXPECT_FALSE(Selection().IsActive());
653
654 Element* const ce = GetDocument().getElementById("ce");
655 ce->focus();
656 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsCaret());
657 EXPECT_TRUE(Selection().IsActive());
658
659 Selection().SelectAll();
660 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
661 EXPECT_TRUE(Selection().IsActive());
662
663 // Here the selection belongs to <divs>'s shadow tree and that tree has a
664 // non-editable parent that is focused.
665 Element* const parent = GetDocument().getElementById("parent");
666 parent->focus();
667 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
668 EXPECT_TRUE(Selection().IsActive()); // Focus is outside editing boundary
669 // but range should still be visible.
670
671 parent->blur(); // Move focus to document body.
672 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
673 EXPECT_TRUE(Selection().IsActive()); // Range is still visible.
674 }
675
676 // crbug.com/707143
677 TEST_F(FrameSelectionTest, RangeContainsFocus) {
678 SetBodyContent(
679 "<div>"
680 " <div>"
681 " <span id='start'>start</span>"
682 " </div>"
683 " <a href='www' id='alink'>link</a>"
684 " <div>line 1</div>"
685 " <div id='middle'>line 2</div>"
686 " <div>line 3</div>"
687 " <div>line 4</div>"
688 " <span id='end'>end</span>"
689 " <div></div>"
690 "</div>");
691 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
692 EXPECT_FALSE(Selection().IsActive());
693
694 Element* const start = GetDocument().getElementById("start");
695 Element* const end = GetDocument().getElementById("end");
696 Selection().SetSelection(
697 SelectionInDOMTree::Builder()
698 .SetBaseAndExtent(Position(start, 0), Position(end, 0))
699 .Build());
700 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
701 EXPECT_TRUE(Selection().IsActive());
702
703 Element* const alink = GetDocument().getElementById("alink");
704 alink->focus();
705 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
706 EXPECT_TRUE(Selection().IsActive()); // Range still visible.
707 }
708
709 // crbug.com/707143
710 TEST_F(FrameSelectionTest, RangeOutsideFocus) {
711 // Here the selection sits on a subtree that hasn't the focused element.
712 // This test case is the reason why didn't gave FrameSelection::IsActive() the
713 // name "HasFocus()". Even when the selection's DOM nodes are completely
714 // disconnected from the focused node, we still want the selection to be
715 // visible (thus "active").
716 SetBodyContent(
717 "<a href='www' id='alink'>link</a>"
718 "<div>"
719 " <div>"
720 " <span id='start'>start</span>"
721 " </div>"
722 " <div>line 1</div>"
723 " <div id='middle'>line 2</div>"
724 " <div>line 3</div>"
725 " <div>line 4</div>"
726 " <span id='end'>end</span>"
727 " <div></div>"
728 "</div>");
729 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
730 EXPECT_FALSE(Selection().IsActive());
731
732 Element* const start = GetDocument().getElementById("start");
733 Element* const end = GetDocument().getElementById("end");
734 Selection().SetSelection(
735 SelectionInDOMTree::Builder()
736 .SetBaseAndExtent(Position(start, 0), Position(end, 0))
737 .Build());
738 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
739 EXPECT_TRUE(Selection().IsActive());
740
741 Element* const alink = GetDocument().getElementById("alink");
742 alink->focus();
743 EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
744 EXPECT_TRUE(Selection().IsActive()); // Range still visible.
745 }
746
352 } // namespace blink 747 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698