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

Unified 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ios/web/navigation/crw_session_controller.mm
diff --git a/ios/web/navigation/crw_session_controller.mm b/ios/web/navigation/crw_session_controller.mm
index 05f8f476bf33e2502a217d674c12dc2da33b6624..430ff519e3430404bca69eb035a1ce4f253c4084 100644
--- a/ios/web/navigation/crw_session_controller.mm
+++ b/ios/web/navigation/crw_session_controller.mm
@@ -132,6 +132,9 @@ NSString* const kXCallbackParametersKey = @"xCallbackParameters";
// Return the PageTransition for the underlying navigationItem at |index| in
// |entries_|
- (ui::PageTransition)transitionForIndex:(NSUInteger)index;
+// Returns YES if the PageTransition for the underlying navigationItem at
+// |index| in |entries_| has ui::PAGE_TRANSITION_IS_REDIRECT_MASK.
+- (BOOL)isRedirectTransitionForEntryAtIndex:(NSInteger)index;
@end
@implementation CRWSessionController
@@ -612,101 +615,47 @@ NSString* const kXCallbackParametersKey = @"xCallbackParameters";
}
- (BOOL)canGoBack {
- if ([_entries count] == 0)
- return NO;
-
- // A transient entry behaves from a user perspective in most ways like a
- // committed entry, so allow going back from a transient entry since this
- // object already has at least one committed entry.
- if (_transientEntry)
- return YES;
-
- NSInteger lastNonRedirectedIndex = _currentNavigationIndex;
- while (lastNonRedirectedIndex >= 0 &&
- ui::PageTransitionIsRedirect(
- [self transitionForIndex:lastNonRedirectedIndex])) {
- --lastNonRedirectedIndex;
- }
-
- return lastNonRedirectedIndex > 0;
+ return [self canGoDelta:-1];
}
- (BOOL)canGoForward {
- // In case there are pending entries return no since when the entry will be
- // committed the history will be cleared from that point forward.
- if (_pendingEntry)
- return NO;
- // If the current index is less than the last element, there are entries to
- // go forward to.
- const NSInteger count = [_entries count];
- return count && _currentNavigationIndex < (count - 1);
+ return [self canGoDelta:1];
}
-- (void)goBack {
- if (![self canGoBack])
- return;
-
- BOOL hadTransientEntry = _transientEntry != nil;
-
- [self discardNonCommittedEntries];
-
- // Going back from a transient entry doesn't require anything beyond
- // discarding the pending entry.
- if (hadTransientEntry)
- return;
-
- base::RecordAction(UserMetricsAction("Back"));
- _previousNavigationIndex = _currentNavigationIndex;
- // To stop the user getting 'stuck' on redirecting pages they weren't even
- // aware existed, it is necessary to pass over pages that would immediately
- // result in a redirect (the entry *before* the redirected page).
- while (_currentNavigationIndex &&
- [self transitionForIndex:_currentNavigationIndex] &
- ui::PAGE_TRANSITION_IS_REDIRECT_MASK) {
- --_currentNavigationIndex;
- }
+- (BOOL)canGoDelta:(int)delta {
+ NSInteger index = [self indexOfEntryForDelta:delta];
+ return 0 <= index && static_cast<NSUInteger>(index) < _entries.count;
+}
- if (_currentNavigationIndex)
- --_currentNavigationIndex;
+- (void)goBack {
+ [self goDelta:-1];
}
- (void)goForward {
- [self discardTransientEntry];
-
- base::RecordAction(UserMetricsAction("Forward"));
- if (_currentNavigationIndex + 1 < static_cast<NSInteger>([_entries count])) {
- _previousNavigationIndex = _currentNavigationIndex;
- ++_currentNavigationIndex;
- }
- // To reduce the chance of a redirect kicking in (truncating the history
- // stack) we skip over any pages that might do this; we detect this by
- // looking for when the *next* page had rediection transition type (was
- // auto redirected to).
- while (_currentNavigationIndex + 1 <
- (static_cast<NSInteger>([_entries count])) &&
- ([self transitionForIndex:_currentNavigationIndex + 1] &
- ui::PAGE_TRANSITION_IS_REDIRECT_MASK)) {
- ++_currentNavigationIndex;
- }
+ [self goDelta:1];
}
- (void)goDelta:(int)delta {
- // Store the navigation index at the start of this function, as |-goForward|
- // and |-goBack| will incrementally reset |_previousNavigationIndex| each time
- // they are called.
- NSInteger previousNavigationIndex = self.currentNavigationIndex;
+ if (delta == 0 || ![self canGoDelta:delta])
+ return;
+
+ NSInteger oldNavigationIndex = self.currentNavigationIndex;
+ NSInteger newNavigationIndex = [self indexOfEntryForDelta:delta];
+
if (delta < 0) {
- while ([self canGoBack] && delta < 0) {
- [self goBack];
- ++delta;
+ [self discardNonCommittedEntries];
+ for (int i = delta; i < 0; i++) {
+ base::RecordAction(UserMetricsAction("Back"));
}
- } else {
- while ([self canGoForward] && delta > 0) {
- [self goForward];
- --delta;
+ } else if (delta > 0) {
+ [self discardTransientEntry];
+ for (int i = 0; i < delta; i++) {
+ base::RecordAction(UserMetricsAction("Forward"));
}
}
- _previousNavigationIndex = previousNavigationIndex;
+
+ _currentNavigationIndex = newNavigationIndex;
+ _previousNavigationIndex = oldNavigationIndex;
}
- (void)goToEntry:(CRWSessionEntry*)entry {
@@ -844,6 +793,53 @@ NSString* const kXCallbackParametersKey = @"xCallbackParameters";
_useDesktopUserAgentForNextPendingEntry = YES;
}
+- (NSInteger)indexOfEntryForDelta:(int)delta {
+ NSInteger result = _currentNavigationIndex;
+ if (delta < 0) {
+ if (_transientEntry) {
+ // Going back from transient entry is a matter of discarding it and there
+ // is no need to move navigation index back.
+ delta++;
+ }
+
+ while (delta < 0) {
+ // To stop the user getting 'stuck' on redirecting pages they weren't
+ // even aware existed, it is necessary to pass over pages that would
+ // immediately result in a redirect (the entry *before* the redirected
+ // page).
+ while (result > 0 && [self isRedirectTransitionForEntryAtIndex:result]) {
+ --result;
+ }
+ --result;
+ ++delta;
+ }
+ } else if (delta > 0) {
+ NSInteger count = static_cast<NSInteger>([_entries count]);
+ if (_pendingEntry) {
+ // Chrome for iOS does not allow forward navigation if there is another
+ // pending navigation in progress. Returning invalid index indicates that
+ // forward navigation will not be allowed (and |NSNotFound| works for
+ // that). This is different from other platforms which allow forward
+ // navigation if pending entry exist.
+ // TODO(crbug.com/661858): Remove this once back-forward navigation uses
+ // pending index.
+ return NSNotFound;
+ }
+
+ while (delta > 0) {
+ ++result;
+ --delta;
+ // As with going back, skip over redirects.
+ while (result + 1 < count &&
+ [self isRedirectTransitionForEntryAtIndex:result + 1]) {
+ ++result;
+ }
+ }
+ }
+
+ return result;
+}
+
#pragma mark -
#pragma mark Private methods
@@ -886,4 +882,9 @@ NSString* const kXCallbackParametersKey = @"xCallbackParameters";
return [[CRWSessionEntry alloc] initWithNavigationItem:std::move(item)];
}
+- (BOOL)isRedirectTransitionForEntryAtIndex:(NSInteger)index {
+ ui::PageTransition transition = [self transitionForIndex:index];
+ 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#
+}
+
@end
« 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