Chromium Code Reviews| 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 1bb37874fe17199af3b6370eb673a0b99eac87df..e367d21bd3b02c21961cb1b7a9d54a66f6899003 100644 |
| --- a/ios/web/navigation/crw_session_controller.mm |
| +++ b/ios/web/navigation/crw_session_controller.mm |
| @@ -152,6 +152,11 @@ - (void)setPendingItemIndex:(NSInteger)pendingItemIndex { |
| DCHECK(_pendingItemIndex == -1 || self.pendingItem); |
| } |
| +- (BOOL)canPruneAllButLastCommittedItem { |
| + return self.currentNavigationIndex != -1 && self.pendingItemIndex == -1 && |
| + !self.transientItem; |
| +} |
| + |
| - (const web::ScopedNavigationItemImplList&)items { |
| return _items; |
| } |
| @@ -486,35 +491,44 @@ - (void)discardTransientItem { |
| _transientItem.reset(); |
| } |
| -- (void)insertStateFromSessionController:(CRWSessionController*)sourceSession { |
| - DCHECK(sourceSession); |
| +- (void)copyStateFromSessionControllerAndPrune:(CRWSessionController*)source { |
| + DCHECK(source); |
| + if (!self.canPruneAllButLastCommittedItem) |
| + return; |
| // The other session may not have any items, in which case there is nothing |
| - // to insert. The other session's currentItem will be bogus in such cases, so |
| - // ignore it and return early. |
| - web::ScopedNavigationItemImplList& sourceItems = sourceSession->_items; |
| + // to insert. |
| + const web::ScopedNavigationItemImplList& sourceItems = source->_items; |
| if (sourceItems.empty()) |
| return; |
| - // Cycle through the items from the other session and insert them before any |
| - // items from this session. Do not copy anything that comes after the other |
| - // session's current item. |
| - NSInteger lastIndexToCopy = sourceSession.currentNavigationIndex; |
| - for (NSInteger i = 0; i <= lastIndexToCopy; ++i) { |
| - std::unique_ptr<web::NavigationItemImpl> sourceItemCopy = |
| - base::MakeUnique<web::NavigationItemImpl>(*sourceItems[i]); |
| - _items.insert(_items.begin() + i, std::move(sourceItemCopy)); |
| + // Early return if there's no committed source item. |
| + if (!source.lastCommittedItem) |
| + return; |
| + |
| + // Copy |sourceItems| into a new NavigationItemList. |mergedItems| is needs |
| + // to be large enough for all items in |source| preceding |
| + // |sourceCurrentIndex|, the |source|'s current item, and |self|'s current |
| + // item, which comes out to |sourceCurrentIndex| + 2. |
| + DCHECK_GT(source.currentNavigationIndex, -1); |
| + size_t sourceCurrentIndex = |
| + static_cast<size_t>(source.currentNavigationIndex); |
| + web::ScopedNavigationItemImplList mergedItems(sourceCurrentIndex + 2); |
| + for (size_t index = 0; index <= sourceCurrentIndex; ++index) { |
| + mergedItems[index] = |
| + base::MakeUnique<web::NavigationItemImpl>(*sourceItems[index]); |
| } |
| + mergedItems.back() = std::move(_items[self.currentNavigationIndex]); |
|
Eugene But (OOO till 7-30)
2017/03/15 23:22:10
Should this be push_back?
kkhorimoto
2017/03/15 23:28:33
No, push_back() will add an extra pointer at the e
|
| + |
| + // Use |mergedItems| as the session history. |
| + std::swap(mergedItems, _items); |
| // Update state to reflect inserted NavigationItems. |
| _previousNavigationIndex = -1; |
| - _currentNavigationIndex += lastIndexToCopy + 1; |
| - if (self.pendingItemIndex != -1) |
| - self.pendingItemIndex += lastIndexToCopy + 1; |
| + _currentNavigationIndex = self.items.size() - 1; |
| DCHECK_LT(static_cast<NSUInteger>(_currentNavigationIndex), |
| self.items.size()); |
| - DCHECK(self.pendingItemIndex == -1 || self.pendingItem); |
| } |
| - (void)goToItemAtIndex:(NSInteger)index { |