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

Side by Side Diff: third_party/WebKit/Source/core/page/FocusController.cpp

Issue 2562753003: Fix focus navigation getting stuck (Closed)
Patch Set: Clean up Created 4 years 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
« no previous file with comments | « third_party/WebKit/LayoutTests/shadow-dom/crashes/focus-navigation-infinite-loop.html ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Nuanti Ltd. 3 * Copyright (C) 2008 Nuanti Ltd.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 // @return The focus element that comes after/before start element. 551 // @return The focus element that comes after/before start element.
552 // 552 //
553 // [1] 553 // [1]
554 // https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navi gation 554 // https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navi gation
555 // [2] https://w3c.github.io/webcomponents/spec/shadow/#focus-navigation 555 // [2] https://w3c.github.io/webcomponents/spec/shadow/#focus-navigation
556 inline Element* findFocusableElementInternal(WebFocusType type, 556 inline Element* findFocusableElementInternal(WebFocusType type,
557 ScopedFocusNavigation& scope) { 557 ScopedFocusNavigation& scope) {
558 Element* found = (type == WebFocusTypeForward) 558 Element* found = (type == WebFocusTypeForward)
559 ? nextFocusableElement(scope) 559 ? nextFocusableElement(scope)
560 : previousFocusableElement(scope); 560 : previousFocusableElement(scope);
561 scope.setCurrentElement(found);
hayato 2016/12/13 05:41:57 It does not look a good idea to call setCurrentEle
kochi 2016/12/13 07:20:37 Agreed.
561 return found; 562 return found;
562 } 563 }
563 564
564 Element* findFocusableElementRecursivelyForward(ScopedFocusNavigation& scope) { 565 Element* findFocusableElementRecursivelyForward(ScopedFocusNavigation& scope) {
565 // Starting element is exclusive. 566 // Starting element is exclusive.
566 Element* found = findFocusableElementInternal(WebFocusTypeForward, scope); 567 while (Element* found =
567 while (found) { 568 findFocusableElementInternal(WebFocusTypeForward, scope)) {
568 if (isShadowHostDelegatesFocus(*found)) { 569 if (isShadowHostDelegatesFocus(*found)) {
569 // If tabindex is positive, find focusable element inside its shadow tree. 570 // If tabindex is positive, find focusable element inside its shadow tree.
570 if (found->tabIndex() >= 0 && 571 if (found->tabIndex() >= 0 &&
571 isShadowHostWithoutCustomFocusLogic(*found)) { 572 isShadowHostWithoutCustomFocusLogic(*found)) {
572 ScopedFocusNavigation innerScope = 573 ScopedFocusNavigation innerScope =
573 ScopedFocusNavigation::ownedByShadowHost(*found); 574 ScopedFocusNavigation::ownedByShadowHost(*found);
574 if (Element* foundInInnerFocusScope = 575 if (Element* foundInInnerFocusScope =
575 findFocusableElementRecursivelyForward(innerScope)) 576 findFocusableElementRecursivelyForward(innerScope))
576 return foundInInnerFocusScope; 577 return foundInInnerFocusScope;
577 } 578 }
578 // Skip to the next element in the same scope. 579 // Skip to the next element in the same scope.
579 found = findFocusableElementInternal(WebFocusTypeForward, scope);
580 continue; 580 continue;
581 } 581 }
582 if (!isNonFocusableFocusScopeOwner(*found)) 582 if (!isNonFocusableFocusScopeOwner(*found))
583 return found; 583 return found;
584 584
585 // Now |found| is on a non focusable scope owner (either shadow host or 585 // Now |found| is on a non focusable scope owner (either shadow host or
586 // <shadow> or slot) Find inside the inward scope and return it if found. 586 // <shadow> or slot) Find inside the inward scope and return it if found.
587 // Otherwise continue searching in the same scope. 587 // Otherwise continue searching in the same scope.
588 ScopedFocusNavigation innerScope = 588 ScopedFocusNavigation innerScope =
589 ScopedFocusNavigation::ownedByNonFocusableFocusScopeOwner(*found); 589 ScopedFocusNavigation::ownedByNonFocusableFocusScopeOwner(*found);
590 if (Element* foundInInnerFocusScope = 590 if (Element* foundInInnerFocusScope =
591 findFocusableElementRecursivelyForward(innerScope)) 591 findFocusableElementRecursivelyForward(innerScope))
592 return foundInInnerFocusScope; 592 return foundInInnerFocusScope;
593
594 scope.setCurrentElement(found);
595 found = findFocusableElementInternal(WebFocusTypeForward, scope);
596 } 593 }
597 return nullptr; 594 return nullptr;
598 } 595 }
599 596
600 Element* findFocusableElementRecursivelyBackward(ScopedFocusNavigation& scope) { 597 Element* findFocusableElementRecursivelyBackward(ScopedFocusNavigation& scope) {
601 // Starting element is exclusive. 598 // Starting element is exclusive.
602 Element* found = findFocusableElementInternal(WebFocusTypeBackward, scope); 599 while (Element* found =
603 600 findFocusableElementInternal(WebFocusTypeBackward, scope)) {
604 while (found) {
605 // Now |found| is on a focusable shadow host. 601 // Now |found| is on a focusable shadow host.
606 // Find inside shadow backwards. If any focusable element is found, return 602 // Find inside shadow backwards. If any focusable element is found, return
607 // it, otherwise return the host itself. 603 // it, otherwise return the host itself.
608 if (isKeyboardFocusableShadowHost(*found)) { 604 if (isKeyboardFocusableShadowHost(*found)) {
609 ScopedFocusNavigation innerScope = 605 ScopedFocusNavigation innerScope =
610 ScopedFocusNavigation::ownedByShadowHost(*found); 606 ScopedFocusNavigation::ownedByShadowHost(*found);
611 Element* foundInInnerFocusScope = 607 Element* foundInInnerFocusScope =
612 findFocusableElementRecursivelyBackward(innerScope); 608 findFocusableElementRecursivelyBackward(innerScope);
613 if (foundInInnerFocusScope) 609 if (foundInInnerFocusScope)
614 return foundInInnerFocusScope; 610 return foundInInnerFocusScope;
615 if (isShadowHostDelegatesFocus(*found)) { 611 if (isShadowHostDelegatesFocus(*found))
616 found = findFocusableElementInternal(WebFocusTypeBackward, scope);
617 continue; 612 continue;
618 }
619 return found; 613 return found;
620 } 614 }
621 615
622 // If delegatesFocus is true and tabindex is negative, skip the whole shadow 616 // If delegatesFocus is true and tabindex is negative, skip the whole shadow
623 // tree under the shadow host. 617 // tree under the shadow host.
624 if (isShadowHostDelegatesFocus(*found) && found->tabIndex() < 0) { 618 if (isShadowHostDelegatesFocus(*found) && found->tabIndex() < 0)
625 found = findFocusableElementInternal(WebFocusTypeBackward, scope);
626 continue; 619 continue;
627 }
628 620
629 // Now |found| is on a non focusable scope owner (either shadow host or 621 // Now |found| is on a non focusable scope owner (a shadow host, a <shadow>
630 // <shadow> or slot). Find focusable element in descendant scope. If not 622 // or a slot). Find focusable element in descendant scope. If not found,
631 // found, find next focusable element within the current scope. 623 // find the next focusable element within the current scope.
632 if (isNonFocusableFocusScopeOwner(*found)) { 624 if (isNonFocusableFocusScopeOwner(*found)) {
633 ScopedFocusNavigation innerScope = 625 ScopedFocusNavigation innerScope =
634 ScopedFocusNavigation::ownedByNonFocusableFocusScopeOwner(*found); 626 ScopedFocusNavigation::ownedByNonFocusableFocusScopeOwner(*found);
635 Element* foundInInnerFocusScope = 627 if (Element* foundInInnerFocusScope =
636 findFocusableElementRecursivelyBackward(innerScope); 628 findFocusableElementRecursivelyBackward(innerScope))
637
638 if (foundInInnerFocusScope)
639 return foundInInnerFocusScope; 629 return foundInInnerFocusScope;
640 found = findFocusableElementInternal(WebFocusTypeBackward, scope);
641 continue; 630 continue;
642 } 631 }
643 if (!isShadowHostDelegatesFocus(*found)) 632 if (!isShadowHostDelegatesFocus(*found))
644 return found; 633 return found;
645
646 scope.setCurrentElement(found);
647 found = findFocusableElementInternal(WebFocusTypeBackward, scope);
648 } 634 }
649 return nullptr; 635 return nullptr;
650 } 636 }
651 637
652 Element* findFocusableElementRecursively(WebFocusType type, 638 Element* findFocusableElementRecursively(WebFocusType type,
653 ScopedFocusNavigation& scope) { 639 ScopedFocusNavigation& scope) {
654 return (type == WebFocusTypeForward) 640 return (type == WebFocusTypeForward)
655 ? findFocusableElementRecursivelyForward(scope) 641 ? findFocusableElementRecursivelyForward(scope)
656 : findFocusableElementRecursivelyBackward(scope); 642 : findFocusableElementRecursivelyBackward(scope);
657 } 643 }
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after
1411 1397
1412 return consumed; 1398 return consumed;
1413 } 1399 }
1414 1400
1415 DEFINE_TRACE(FocusController) { 1401 DEFINE_TRACE(FocusController) {
1416 visitor->trace(m_page); 1402 visitor->trace(m_page);
1417 visitor->trace(m_focusedFrame); 1403 visitor->trace(m_focusedFrame);
1418 } 1404 }
1419 1405
1420 } // namespace blink 1406 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/LayoutTests/shadow-dom/crashes/focus-navigation-infinite-loop.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698