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

Side by Side Diff: ios/web/navigation/crw_session_controller.mm

Issue 2482983003: Reland: [ios] Refactored back-forward navigation in CRWSessionController. (Closed)
Patch Set: Fix Created 4 years, 1 month 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 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 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 #import "ios/web/navigation/crw_session_controller.h" 5 #import "ios/web/navigation/crw_session_controller.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <utility> 10 #include <utility>
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 - (void)discardTransientEntry; 125 - (void)discardTransientEntry;
126 // Create a new autoreleased session entry. 126 // Create a new autoreleased session entry.
127 - (CRWSessionEntry*)sessionEntryWithURL:(const GURL&)url 127 - (CRWSessionEntry*)sessionEntryWithURL:(const GURL&)url
128 referrer:(const web::Referrer&)referrer 128 referrer:(const web::Referrer&)referrer
129 transition:(ui::PageTransition)transition 129 transition:(ui::PageTransition)transition
130 useDesktopUserAgent:(BOOL)useDesktopUserAgent 130 useDesktopUserAgent:(BOOL)useDesktopUserAgent
131 rendererInitiated:(BOOL)rendererInitiated; 131 rendererInitiated:(BOOL)rendererInitiated;
132 // Return the PageTransition for the underlying navigationItem at |index| in 132 // Return the PageTransition for the underlying navigationItem at |index| in
133 // |entries_| 133 // |entries_|
134 - (ui::PageTransition)transitionForIndex:(NSUInteger)index; 134 - (ui::PageTransition)transitionForIndex:(NSUInteger)index;
135 // Returns YES if the PageTransition for the underlying navigationItem at
136 // |index| in |entries_| has ui::PAGE_TRANSITION_IS_REDIRECT_MASK.
137 - (BOOL)isRedirectTransitionForEntryAtIndex:(NSInteger)index;
135 @end 138 @end
136 139
137 @implementation CRWSessionController 140 @implementation CRWSessionController
138 141
139 @synthesize tabId = _tabId; 142 @synthesize tabId = _tabId;
140 @synthesize currentNavigationIndex = _currentNavigationIndex; 143 @synthesize currentNavigationIndex = _currentNavigationIndex;
141 @synthesize previousNavigationIndex = _previousNavigationIndex; 144 @synthesize previousNavigationIndex = _previousNavigationIndex;
142 @synthesize entries = _entries; 145 @synthesize entries = _entries;
143 @synthesize windowName = _windowName; 146 @synthesize windowName = _windowName;
144 @synthesize lastVisitedTimestamp = _lastVisitedTimestamp; 147 @synthesize lastVisitedTimestamp = _lastVisitedTimestamp;
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 } 608 }
606 } 609 }
607 DCHECK_LT((NSUInteger)_currentNavigationIndex, [_entries count]); 610 DCHECK_LT((NSUInteger)_currentNavigationIndex, [_entries count]);
608 } 611 }
609 612
610 - (ui::PageTransition)transitionForIndex:(NSUInteger)index { 613 - (ui::PageTransition)transitionForIndex:(NSUInteger)index {
611 return [[_entries objectAtIndex:index] navigationItem]->GetTransitionType(); 614 return [[_entries objectAtIndex:index] navigationItem]->GetTransitionType();
612 } 615 }
613 616
614 - (BOOL)canGoBack { 617 - (BOOL)canGoBack {
615 if ([_entries count] == 0) 618 return [self canGoDelta:-1];
616 return NO;
617
618 // A transient entry behaves from a user perspective in most ways like a
619 // committed entry, so allow going back from a transient entry since this
620 // object already has at least one committed entry.
621 if (_transientEntry)
622 return YES;
623
624 NSInteger lastNonRedirectedIndex = _currentNavigationIndex;
625 while (lastNonRedirectedIndex >= 0 &&
626 ui::PageTransitionIsRedirect(
627 [self transitionForIndex:lastNonRedirectedIndex])) {
628 --lastNonRedirectedIndex;
629 }
630
631 return lastNonRedirectedIndex > 0;
632 } 619 }
633 620
634 - (BOOL)canGoForward { 621 - (BOOL)canGoForward {
635 // In case there are pending entries return no since when the entry will be 622 return [self canGoDelta:1];
636 // committed the history will be cleared from that point forward. 623 }
637 if (_pendingEntry) 624
638 return NO; 625 - (BOOL)canGoDelta:(int)delta {
639 // If the current index is less than the last element, there are entries to 626 NSInteger index = [self indexOfEntryForDelta:delta];
640 // go forward to. 627 return 0 <= index && static_cast<NSUInteger>(index) < _entries.count;
641 const NSInteger count = [_entries count];
642 return count && _currentNavigationIndex < (count - 1);
643 } 628 }
644 629
645 - (void)goBack { 630 - (void)goBack {
646 if (![self canGoBack]) 631 [self goDelta:-1];
647 return;
648
649 BOOL hadTransientEntry = _transientEntry != nil;
650
651 [self discardNonCommittedEntries];
652
653 // Going back from a transient entry doesn't require anything beyond
654 // discarding the pending entry.
655 if (hadTransientEntry)
656 return;
657
658 base::RecordAction(UserMetricsAction("Back"));
659 _previousNavigationIndex = _currentNavigationIndex;
660 // To stop the user getting 'stuck' on redirecting pages they weren't even
661 // aware existed, it is necessary to pass over pages that would immediately
662 // result in a redirect (the entry *before* the redirected page).
663 while (_currentNavigationIndex &&
664 [self transitionForIndex:_currentNavigationIndex] &
665 ui::PAGE_TRANSITION_IS_REDIRECT_MASK) {
666 --_currentNavigationIndex;
667 }
668
669 if (_currentNavigationIndex)
670 --_currentNavigationIndex;
671 } 632 }
672 633
673 - (void)goForward { 634 - (void)goForward {
674 [self discardTransientEntry]; 635 [self goDelta:1];
675
676 base::RecordAction(UserMetricsAction("Forward"));
677 if (_currentNavigationIndex + 1 < static_cast<NSInteger>([_entries count])) {
678 _previousNavigationIndex = _currentNavigationIndex;
679 ++_currentNavigationIndex;
680 }
681 // To reduce the chance of a redirect kicking in (truncating the history
682 // stack) we skip over any pages that might do this; we detect this by
683 // looking for when the *next* page had rediection transition type (was
684 // auto redirected to).
685 while (_currentNavigationIndex + 1 <
686 (static_cast<NSInteger>([_entries count])) &&
687 ([self transitionForIndex:_currentNavigationIndex + 1] &
688 ui::PAGE_TRANSITION_IS_REDIRECT_MASK)) {
689 ++_currentNavigationIndex;
690 }
691 } 636 }
692 637
693 - (void)goDelta:(int)delta { 638 - (void)goDelta:(int)delta {
694 // Store the navigation index at the start of this function, as |-goForward| 639 if (delta == 0 || ![self canGoDelta:delta])
695 // and |-goBack| will incrementally reset |_previousNavigationIndex| each time 640 return;
696 // they are called. 641
697 NSInteger previousNavigationIndex = self.currentNavigationIndex; 642 NSInteger oldNavigationIndex = self.currentNavigationIndex;
643 NSInteger newNavigationIndex = [self indexOfEntryForDelta:delta];
644
698 if (delta < 0) { 645 if (delta < 0) {
699 while ([self canGoBack] && delta < 0) { 646 [self discardNonCommittedEntries];
700 [self goBack]; 647 for (int i = delta; i < 0; i++) {
701 ++delta; 648 base::RecordAction(UserMetricsAction("Back"));
702 } 649 }
703 } else { 650 } else if (delta > 0) {
704 while ([self canGoForward] && delta > 0) { 651 [self discardTransientEntry];
705 [self goForward]; 652 for (int i = 0; i < delta; i++) {
706 --delta; 653 base::RecordAction(UserMetricsAction("Forward"));
707 } 654 }
708 } 655 }
709 _previousNavigationIndex = previousNavigationIndex; 656
657 _currentNavigationIndex = newNavigationIndex;
658 _previousNavigationIndex = oldNavigationIndex;
710 } 659 }
711 660
712 - (void)goToEntry:(CRWSessionEntry*)entry { 661 - (void)goToEntry:(CRWSessionEntry*)entry {
713 DCHECK(entry); 662 DCHECK(entry);
714 663
715 [self discardTransientEntry]; 664 [self discardTransientEntry];
716 665
717 // Check that |entries_| still contains |entry|. |entry| could have been 666 // Check that |entries_| still contains |entry|. |entry| could have been
718 // removed by -clearForwardEntries. 667 // removed by -clearForwardEntries.
719 if ([_entries containsObject:entry]) { 668 if ([_entries containsObject:entry]) {
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 return [_entries objectAtIndex:index]; 786 return [_entries objectAtIndex:index];
838 } 787 }
839 788
840 - (void)useDesktopUserAgentForNextPendingEntry { 789 - (void)useDesktopUserAgentForNextPendingEntry {
841 if (_pendingEntry) 790 if (_pendingEntry)
842 [_pendingEntry navigationItem]->SetIsOverridingUserAgent(true); 791 [_pendingEntry navigationItem]->SetIsOverridingUserAgent(true);
843 else 792 else
844 _useDesktopUserAgentForNextPendingEntry = YES; 793 _useDesktopUserAgentForNextPendingEntry = YES;
845 } 794 }
846 795
796 - (NSInteger)indexOfEntryForDelta:(int)delta {
797 NSInteger result = _currentNavigationIndex;
798 if (delta < 0) {
799 if (_transientEntry) {
800 // Going back from transient entry is a matter of discarding it and there
801 // is no need to move navigation index back.
802 delta++;
803 }
804
805 while (delta < 0) {
806 // To stop the user getting 'stuck' on redirecting pages they weren't
807 // even aware existed, it is necessary to pass over pages that would
808 // immediately result in a redirect (the entry *before* the redirected
809 // page).
810 while (result > 0 && [self isRedirectTransitionForEntryAtIndex:result]) {
811 --result;
812 }
813 --result;
814 ++delta;
815 }
816 } else if (delta > 0) {
817 NSInteger count = static_cast<NSInteger>([_entries count]);
818 if (_pendingEntry) {
819 // Chrome for iOS does not allow forward navigation if there is another
820 // pending navigation in progress. Returning invalid index indicates that
821 // forward navigation will not be allowed (and |NSNotFound| works for
822 // that). This is different from other platforms which allow forward
823 // navigation if pending entry exist.
824 // TODO(crbug.com/661858): Remove this once back-forward navigation uses
825 // pending index.
826 return NSNotFound;
827 }
828
829 while (delta > 0) {
830 ++result;
831 --delta;
832 // As with going back, skip over redirects.
833 while (result + 1 < count &&
834 [self isRedirectTransitionForEntryAtIndex:result + 1]) {
835 ++result;
836 }
837 }
838 }
839
840 return result;
841 }
842
847 #pragma mark - 843 #pragma mark -
848 #pragma mark Private methods 844 #pragma mark Private methods
849 845
850 - (NSString*)uniqueID { 846 - (NSString*)uniqueID {
851 CFUUIDRef uuidRef = CFUUIDCreate(NULL); 847 CFUUIDRef uuidRef = CFUUIDCreate(NULL);
852 CFStringRef uuidStringRef = CFUUIDCreateString(NULL, uuidRef); 848 CFStringRef uuidStringRef = CFUUIDCreateString(NULL, uuidRef);
853 CFRelease(uuidRef); 849 CFRelease(uuidRef);
854 850
855 NSString* uuid = 851 NSString* uuid =
856 [NSString stringWithString:base::mac::ObjCCastStrict<NSString>( 852 [NSString stringWithString:base::mac::ObjCCastStrict<NSString>(
(...skipping 22 matching lines...) Expand all
879 } 875 }
880 std::unique_ptr<web::NavigationItemImpl> item(new web::NavigationItemImpl()); 876 std::unique_ptr<web::NavigationItemImpl> item(new web::NavigationItemImpl());
881 item->SetURL(loaded_url); 877 item->SetURL(loaded_url);
882 item->SetReferrer(referrer); 878 item->SetReferrer(referrer);
883 item->SetTransitionType(transition); 879 item->SetTransitionType(transition);
884 item->SetIsOverridingUserAgent(useDesktopUserAgent); 880 item->SetIsOverridingUserAgent(useDesktopUserAgent);
885 item->set_is_renderer_initiated(rendererInitiated); 881 item->set_is_renderer_initiated(rendererInitiated);
886 return [[CRWSessionEntry alloc] initWithNavigationItem:std::move(item)]; 882 return [[CRWSessionEntry alloc] initWithNavigationItem:std::move(item)];
887 } 883 }
888 884
885 - (BOOL)isRedirectTransitionForEntryAtIndex:(NSInteger)index {
886 ui::PageTransition transition = [self transitionForIndex:index];
887 return (transition & ui::PAGE_TRANSITION_IS_REDIRECT_MASK) ? YES : NO;
Eugene But (OOO till 7-30) 2016/11/08 04:03:01 https://google.github.io/styleguide/objcguide.xml#
888 }
889
889 @end 890 @end
OLDNEW
« no previous file with comments | « ios/web/navigation/crw_session_controller.h ('k') | ios/web/navigation/crw_session_controller_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698