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

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

Issue 2737203002: Remove CRWSessionEntry. (Closed)
Patch Set: self review Created 3 years, 9 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 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>
11 #include <vector>
12 11
13 #include "base/format_macros.h" 12 #include "base/format_macros.h"
14 #include "base/logging.h" 13 #include "base/logging.h"
15 #import "base/mac/foundation_util.h" 14 #import "base/mac/foundation_util.h"
16 #import "base/mac/scoped_nsobject.h" 15 #import "base/mac/scoped_nsobject.h"
17 #include "base/strings/sys_string_conversions.h" 16 #include "base/strings/sys_string_conversions.h"
18 #include "ios/web/history_state_util.h" 17 #include "ios/web/history_state_util.h"
19 #import "ios/web/navigation/crw_session_certificate_policy_manager.h" 18 #import "ios/web/navigation/crw_session_certificate_policy_manager.h"
20 #import "ios/web/navigation/crw_session_controller+private_constructors.h" 19 #import "ios/web/navigation/crw_session_controller+private_constructors.h"
21 #import "ios/web/navigation/crw_session_entry.h"
22 #import "ios/web/navigation/navigation_item_impl.h" 20 #import "ios/web/navigation/navigation_item_impl.h"
23 #include "ios/web/navigation/navigation_manager_facade_delegate.h" 21 #include "ios/web/navigation/navigation_manager_facade_delegate.h"
24 #import "ios/web/navigation/navigation_manager_impl.h" 22 #import "ios/web/navigation/navigation_manager_impl.h"
25 #include "ios/web/navigation/time_smoother.h" 23 #include "ios/web/navigation/time_smoother.h"
26 #include "ios/web/public/browser_state.h" 24 #include "ios/web/public/browser_state.h"
27 #include "ios/web/public/browser_url_rewriter.h" 25 #include "ios/web/public/browser_url_rewriter.h"
28 #include "ios/web/public/referrer.h" 26 #include "ios/web/public/referrer.h"
29 #include "ios/web/public/ssl_status.h" 27 #include "ios/web/public/ssl_status.h"
30 #import "ios/web/public/web_client.h" 28 #import "ios/web/public/web_client.h"
31 29
32 #if !defined(__has_feature) || !__has_feature(objc_arc) 30 #if !defined(__has_feature) || !__has_feature(objc_arc)
33 #error "This file requires ARC support." 31 #error "This file requires ARC support."
34 #endif 32 #endif
35 33
36 @interface CRWSessionController () { 34 @interface CRWSessionController () {
37 // Weak pointer back to the owning NavigationManager. This is to facilitate 35 // Weak pointer back to the owning NavigationManager. This is to facilitate
38 // the incremental merging of the two classes. 36 // the incremental merging of the two classes.
39 web::NavigationManagerImpl* _navigationManager; 37 web::NavigationManagerImpl* _navigationManager;
40 38
41 // Identifies the index of the current navigation in the CRWSessionEntry 39 // Identifies the index of the current navigation in the NavigationItem
42 // array. 40 // array.
43 NSInteger _currentNavigationIndex; 41 NSInteger _currentNavigationIndex;
44 // Identifies the index of the previous navigation in the CRWSessionEntry 42 // Identifies the index of the previous navigation in the NavigationItem
45 // array. 43 // array.
46 NSInteger _previousNavigationIndex; 44 NSInteger _previousNavigationIndex;
47 // Ordered array of |CRWSessionEntry| objects, one for each site in session
48 // history. End of the list is the most recent load.
49 NSMutableArray* _entries;
50
51 // An entry we haven't gotten a response for yet. This will be discarded
52 // when we navigate again. It's used only so we know what the currently
53 // displayed tab is. It backs the property of the same name and should only
54 // be set through its setter.
55 base::scoped_nsobject<CRWSessionEntry> _pendingEntry;
56
57 // The transient entry, if any. A transient entry is discarded on any
58 // navigation, and is used for representing interstitials that need to be
59 // represented in the session. It backs the property of the same name and
60 // should only be set through its setter.
61 base::scoped_nsobject<CRWSessionEntry> _transientEntry;
62 45
63 // Stores the certificate policies decided by the user. 46 // Stores the certificate policies decided by the user.
64 CRWSessionCertificatePolicyManager* _sessionCertificatePolicyManager; 47 CRWSessionCertificatePolicyManager* _sessionCertificatePolicyManager;
65 48
66 // The browser state associated with this CRWSessionController; 49 // The browser state associated with this CRWSessionController;
67 web::BrowserState* _browserState; // weak 50 web::BrowserState* _browserState; // weak
68 51
69 // Time smoother for navigation entry timestamps; see comment in 52 // Time smoother for navigation item timestamps; see comment in
70 // navigation_controller_impl.h 53 // navigation_controller_impl.h
71 web::TimeSmoother _timeSmoother; 54 web::TimeSmoother _timeSmoother;
55
56 // Backing objects for properties of the same name.
57 web::ScopedNavigationItemImplList _items;
58 // |_pendingItem| only contains a NavigationItem for non-history navigations.
59 // For back/forward navigations within session history, _pendingItemIndex will
60 // be equal to -1, and self.pendingItem will return an item contained within
61 // |_items|.
62 std::unique_ptr<web::NavigationItemImpl> _pendingItem;
63 std::unique_ptr<web::NavigationItemImpl> _transientItem;
Eugene But (OOO till 7-30) 2017/03/09 16:10:58 Old comments for transientEntry looked useful. Is
kkhorimoto 2017/03/09 21:33:54 I've moved the comment to the interface property d
72 } 64 }
73 65
74 // Redefine as readwrite. 66 // Redefine as readwrite.
75 @property(nonatomic, readwrite, assign) NSInteger currentNavigationIndex; 67 @property(nonatomic, readwrite, assign) NSInteger currentNavigationIndex;
76 68
77 // TODO(rohitrao): These properties must be redefined readwrite to work around a 69 // TODO(rohitrao): These properties must be redefined readwrite to work around a
78 // clang bug. crbug.com/228650 70 // clang bug. crbug.com/228650
79 @property(nonatomic, readwrite, strong) NSArray* entries;
80 @property(nonatomic, readwrite, strong) 71 @property(nonatomic, readwrite, strong)
81 CRWSessionCertificatePolicyManager* sessionCertificatePolicyManager; 72 CRWSessionCertificatePolicyManager* sessionCertificatePolicyManager;
82 73
83 // Expose setters for serialization properties. These are exposed in a category 74 // Expose setters for serialization properties. These are exposed in a category
84 // in SessionStorageBuilder, and will be removed as ownership of 75 // in SessionStorageBuilder, and will be removed as ownership of
85 // their backing ivars moves to NavigationManagerImpl. 76 // their backing ivars moves to NavigationManagerImpl.
86 @property(nonatomic, readwrite, getter=isOpenedByDOM) BOOL openedByDOM; 77 @property(nonatomic, readwrite, getter=isOpenedByDOM) BOOL openedByDOM;
87 @property(nonatomic, readwrite, assign) NSInteger previousNavigationIndex; 78 @property(nonatomic, readwrite, assign) NSInteger previousNavigationIndex;
88 79
89 // Removes all entries after currentNavigationIndex_. 80 // Removes all items after currentNavigationIndex_.
90 - (void)clearForwardItems; 81 - (void)clearForwardItems;
91 // Discards the transient entry, if any. 82 // Discards the transient item, if any.
92 - (void)discardTransientItem; 83 - (void)discardTransientItem;
93 // Create a new autoreleased session entry. 84 // Creates a NavigationItemImpl with the specified properties.
94 - (CRWSessionEntry*)sessionEntryWithURL:(const GURL&)url 85 - (std::unique_ptr<web::NavigationItemImpl>)
95 referrer:(const web::Referrer&)referrer 86 itemWithURL:(const GURL&)url
96 transition:(ui::PageTransition)transition 87 referrer:(const web::Referrer&)referrer
97 initiationType: 88 transition:(ui::PageTransition)transition
98 (web::NavigationInitiationType)initiationType; 89 initiationType:(web::NavigationInitiationType)initiationType;
99 // Returns YES if the PageTransition for the underlying navigationItem at 90 // Returns YES if the PageTransition for the underlying navigationItem at
100 // |index| in |entries_| has ui::PAGE_TRANSITION_IS_REDIRECT_MASK. 91 // |index| in |items| has ui::PAGE_TRANSITION_IS_REDIRECT_MASK.
101 - (BOOL)isRedirectTransitionForItemAtIndex:(NSInteger)index; 92 - (BOOL)isRedirectTransitionForItemAtIndex:(size_t)index;
102 // Returns a NavigationItemList containing the NavigationItems from |entries|. 93
103 - (web::NavigationItemList)itemListForEntryList:(NSArray*)entries;
104 @end 94 @end
105 95
106 @implementation CRWSessionController 96 @implementation CRWSessionController
107 97
108 @synthesize currentNavigationIndex = _currentNavigationIndex; 98 @synthesize currentNavigationIndex = _currentNavigationIndex;
109 @synthesize previousNavigationIndex = _previousNavigationIndex; 99 @synthesize previousNavigationIndex = _previousNavigationIndex;
110 @synthesize pendingItemIndex = _pendingItemIndex; 100 @synthesize pendingItemIndex = _pendingItemIndex;
111 @synthesize entries = _entries;
112 @synthesize openedByDOM = _openedByDOM; 101 @synthesize openedByDOM = _openedByDOM;
113 @synthesize sessionCertificatePolicyManager = _sessionCertificatePolicyManager; 102 @synthesize sessionCertificatePolicyManager = _sessionCertificatePolicyManager;
114 103
115 - (instancetype)initWithBrowserState:(web::BrowserState*)browserState 104 - (instancetype)initWithBrowserState:(web::BrowserState*)browserState
116 openedByDOM:(BOOL)openedByDOM { 105 openedByDOM:(BOOL)openedByDOM {
117 self = [super init]; 106 self = [super init];
118 if (self) { 107 if (self) {
119 _openedByDOM = openedByDOM; 108 _openedByDOM = openedByDOM;
120 _browserState = browserState; 109 _browserState = browserState;
121 _entries = [NSMutableArray array];
122 _currentNavigationIndex = -1; 110 _currentNavigationIndex = -1;
123 _previousNavigationIndex = -1; 111 _previousNavigationIndex = -1;
124 _pendingItemIndex = -1; 112 _pendingItemIndex = -1;
125 _sessionCertificatePolicyManager = 113 _sessionCertificatePolicyManager =
126 [[CRWSessionCertificatePolicyManager alloc] init]; 114 [[CRWSessionCertificatePolicyManager alloc] init];
127 } 115 }
128 return self; 116 return self;
129 } 117 }
130 118
131 - (instancetype)initWithBrowserState:(web::BrowserState*)browserState 119 - (instancetype)initWithBrowserState:(web::BrowserState*)browserState
132 navigationItems:(web::ScopedNavigationItemList)items 120 navigationItems:(web::ScopedNavigationItemList)items
133 currentIndex:(NSUInteger)currentIndex { 121 currentIndex:(NSUInteger)currentIndex {
134 self = [super init]; 122 self = [super init];
135 if (self) { 123 if (self) {
136 _browserState = browserState; 124 _browserState = browserState;
137 125 _items = web::CreateScopedNavigationItemImplList(std::move(items));
138 // Create entries array from list of navigations.
139 _entries = [[NSMutableArray alloc] initWithCapacity:items.size()];
140 for (auto& item : items) {
141 base::scoped_nsobject<CRWSessionEntry> entry(
142 [[CRWSessionEntry alloc] initWithNavigationItem:std::move(item)]);
143 [_entries addObject:entry];
144 }
145 self.currentNavigationIndex = currentIndex; 126 self.currentNavigationIndex = currentIndex;
146 // Prior to M34, 0 was used as "no index" instead of -1; adjust for that. 127 if (_items.empty())
Eugene But (OOO till 7-30) 2017/03/09 16:10:58 This comment still looks like a valid one, because
kkhorimoto 2017/03/09 21:33:54 I removed the empty() check. The same result is a
147 if (![_entries count])
148 self.currentNavigationIndex = -1; 128 self.currentNavigationIndex = -1;
149 if (_currentNavigationIndex >= static_cast<NSInteger>(items.size())) { 129 _currentNavigationIndex = std::min(
150 self.currentNavigationIndex = static_cast<NSInteger>(items.size()) - 1; 130 _currentNavigationIndex, static_cast<NSInteger>(_items.size() - 1));
151 }
152 _previousNavigationIndex = -1; 131 _previousNavigationIndex = -1;
153 _pendingItemIndex = -1; 132 _pendingItemIndex = -1;
154 _sessionCertificatePolicyManager = 133 _sessionCertificatePolicyManager =
155 [[CRWSessionCertificatePolicyManager alloc] init]; 134 [[CRWSessionCertificatePolicyManager alloc] init];
156 } 135 }
157 return self; 136 return self;
158 } 137 }
159 138
160 - (id)copyWithZone:(NSZone*)zone { 139 #pragma mark - Accessors
161 CRWSessionController* copy = [[[self class] alloc] init];
162 copy->_openedByDOM = _openedByDOM;
163 copy->_currentNavigationIndex = _currentNavigationIndex;
164 copy->_previousNavigationIndex = _previousNavigationIndex;
165 copy->_pendingItemIndex = _pendingItemIndex;
166 copy->_entries =
167 [[NSMutableArray alloc] initWithArray:_entries copyItems:YES];
168 copy->_sessionCertificatePolicyManager =
169 [_sessionCertificatePolicyManager copy];
170 return copy;
171 }
172 140
173 - (void)setCurrentNavigationIndex:(NSInteger)currentNavigationIndex { 141 - (void)setCurrentNavigationIndex:(NSInteger)currentNavigationIndex {
174 if (_currentNavigationIndex != currentNavigationIndex) { 142 if (_currentNavigationIndex != currentNavigationIndex) {
175 _currentNavigationIndex = currentNavigationIndex; 143 _currentNavigationIndex = currentNavigationIndex;
176 if (_navigationManager) 144 if (_navigationManager)
177 _navigationManager->RemoveTransientURLRewriters(); 145 _navigationManager->RemoveTransientURLRewriters();
178 } 146 }
179 } 147 }
180 148
181 - (void)setPendingItemIndex:(NSInteger)index { 149 - (void)setPendingItemIndex:(NSInteger)pendingItemIndex {
182 DCHECK_GE(index, -1); 150 DCHECK_GE(pendingItemIndex, -1);
183 DCHECK_LT(index, static_cast<NSInteger>(_entries.count)); 151 DCHECK_LT(pendingItemIndex, static_cast<NSInteger>(self.items.size()));
184 _pendingItemIndex = index; 152 _pendingItemIndex = pendingItemIndex;
185 CRWSessionEntry* entry = index != -1 ? _entries[index] : nil; 153 DCHECK(_pendingItemIndex == -1 || self.pendingItem);
186 _pendingEntry.reset(entry);
187 DCHECK(_pendingItemIndex == -1 || _pendingEntry);
188 } 154 }
189 155
156 - (const web::ScopedNavigationItemImplList&)items {
157 return _items;
158 }
159
160 - (web::NavigationItemImpl*)currentItem {
161 if (self.transientItem)
162 return self.transientItem;
163 if (self.pendingItem)
164 return self.pendingItem;
165 return self.lastCommittedItem;
166 }
167
168 - (web::NavigationItemImpl*)visibleItem {
169 // Only return the |pendingItem| for new (non-history), browser-initiated
170 // navigations in order to prevent URL spoof attacks.
171 web::NavigationItemImpl* pendingItem = self.pendingItem;
172 if (pendingItem) {
173 bool isUserInitiated = pendingItem->NavigationInitiationType() ==
174 web::NavigationInitiationType::USER_INITIATED;
175 bool safeToShowPending = isUserInitiated && _pendingItemIndex == -1;
176
177 if (safeToShowPending)
178 return pendingItem;
179 }
180 return self.lastCommittedItem;
181 }
182
183 - (web::NavigationItemImpl*)pendingItem {
184 if (self.pendingItemIndex == -1)
185 return _pendingItem.get();
186 return self.items[self.pendingItemIndex].get();
187 }
188
189 - (web::NavigationItemImpl*)transientItem {
190 return _transientItem.get();
191 }
192
193 - (web::NavigationItemImpl*)lastCommittedItem {
194 NSInteger index = self.currentNavigationIndex;
195 return index == -1 ? nullptr : self.items[index].get();
196 }
197
198 - (web::NavigationItemImpl*)previousItem {
199 NSInteger index = self.previousNavigationIndex;
200 return index == -1 || self.items.empty() ? nullptr : self.items[index].get();
201 }
202
203 - (web::NavigationItemImpl*)lastUserItem {
204 if (self.items.empty())
205 return nil;
206
207 NSInteger index = self.currentNavigationIndex;
208 // This will return the first NavigationItem if all other items are
209 // redirects, regardless of the transition state of the first item.
210 while (index > 0 && [self isRedirectTransitionForItemAtIndex:index])
211 --index;
212
213 return self.items[index].get();
214 }
215
216 - (web::NavigationItemList)backwardItems {
217 web::NavigationItemList items;
218 for (size_t index = _currentNavigationIndex; index > 0; --index) {
219 if (![self isRedirectTransitionForItemAtIndex:index])
220 items.push_back(self.items[index - 1].get());
221 }
222 return items;
223 }
224
225 - (web::NavigationItemList)forwardItems {
226 web::NavigationItemList items;
227 NSUInteger lastNonRedirectedIndex = _currentNavigationIndex + 1;
228 while (lastNonRedirectedIndex < self.items.size()) {
229 web::NavigationItem* item = self.items[lastNonRedirectedIndex].get();
230 if (!ui::PageTransitionIsRedirect(item->GetTransitionType()))
231 items.push_back(item);
232 ++lastNonRedirectedIndex;
233 }
234 return items;
235 }
236
237 #pragma mark - NSObject
238
239 - (NSString*)description {
240 // Create description for |items|.
241 NSMutableString* itemsDescription = [NSMutableString stringWithString:@"[\n"];
242 #ifndef NDEBUG
243 for (const auto& item : self.items)
244 [itemsDescription appendFormat:@"%@\n", item->GetDescription()];
245 #endif
246 [itemsDescription appendString:@"]"];
247 // Create description for |pendingItem| and |transientItem|.
248 NSString* pendingItemDescription = @"(null)";
249 NSString* transientItemDescription = @"(null)";
250 #ifndef NDEBUG
251 if (self.pendingItem)
252 pendingItemDescription = self.pendingItem->GetDescription();
253 if (self.transientItem)
254 transientItemDescription = self.transientItem->GetDescription();
255 #else
256 if (self.pendingItem) {
257 pendingItemDescription =
258 [NSString stringWithFormat:@"%p", self.pendingItem];
259 }
260 if (self.transientItem) {
261 transientItemDescription =
262 [NSString stringWithFormat:@"%p", self.transientItem];
263 }
264 #endif
265 return [NSString stringWithFormat:@"current index: %" PRIdNS
266 @"\nprevious index: %" PRIdNS
267 @"\npending"
268 @" index: %" PRIdNS
269 @"\n%@\npending: %@\ntransient: %@\n",
270 _currentNavigationIndex,
271 _previousNavigationIndex, _pendingItemIndex,
272 itemsDescription, pendingItemDescription,
273 transientItemDescription];
274 }
275
276 #pragma mark - NSCopying
277
278 - (id)copyWithZone:(NSZone*)zone {
279 CRWSessionController* copy = [[[self class] alloc] init];
280 copy->_openedByDOM = _openedByDOM;
281 copy->_currentNavigationIndex = _currentNavigationIndex;
282 copy->_previousNavigationIndex = _previousNavigationIndex;
283 copy->_pendingItemIndex = _pendingItemIndex;
284 copy->_sessionCertificatePolicyManager =
285 [_sessionCertificatePolicyManager copy];
286 for (size_t index = 0; index < self.items.size(); ++index) {
287 std::unique_ptr<web::NavigationItemImpl> itemCopy(
288 new web::NavigationItemImpl(*self.items[index].get()));
Eugene But (OOO till 7-30) 2017/03/09 16:10:58 nit: Do you need |.get()|?
Eugene But (OOO till 7-30) 2017/03/09 16:10:58 nit: s/new/base::MakeUnique
kkhorimoto 2017/03/09 21:33:54 Nope, turns out unique_ptr overrides the * operato
289 copy->_items.push_back(std::move(itemCopy));
290 }
291 return copy;
292 }
293
294 #pragma mark - Public
295
190 - (void)setNavigationManager:(web::NavigationManagerImpl*)navigationManager { 296 - (void)setNavigationManager:(web::NavigationManagerImpl*)navigationManager {
191 _navigationManager = navigationManager; 297 _navigationManager = navigationManager;
192 if (_navigationManager) { 298 if (_navigationManager) {
193 // _browserState will be nullptr if CRWSessionController has been 299 // _browserState will be nullptr if CRWSessionController has been
194 // initialized with -initWithCoder: method. Take _browserState from 300 // initialized with -initWithCoder: method. Take _browserState from
195 // NavigationManagerImpl if that's the case. 301 // NavigationManagerImpl if that's the case.
196 if (!_browserState) { 302 if (!_browserState) {
197 _browserState = _navigationManager->GetBrowserState(); 303 _browserState = _navigationManager->GetBrowserState();
198 } 304 }
199 DCHECK_EQ(_browserState, _navigationManager->GetBrowserState()); 305 DCHECK_EQ(_browserState, _navigationManager->GetBrowserState());
200 } 306 }
201 } 307 }
202 308
203 - (void)setBrowserState:(web::BrowserState*)browserState { 309 - (void)setBrowserState:(web::BrowserState*)browserState {
204 _browserState = browserState; 310 _browserState = browserState;
205 DCHECK(!_navigationManager || 311 DCHECK(!_navigationManager ||
206 _navigationManager->GetBrowserState() == _browserState); 312 _navigationManager->GetBrowserState() == _browserState);
207 } 313 }
208 314
209 - (NSString*)description {
210 return [NSString stringWithFormat:@"current index: %" PRIdNS
211 @"\nprevious index: %" PRIdNS
212 @"\npending index: %" PRIdNS
213 @"\n%@\npending: %@\ntransient: %@\n",
214 _currentNavigationIndex,
215 _previousNavigationIndex, _pendingItemIndex,
216 _entries, _pendingEntry.get(),
217 _transientEntry.get()];
218 }
219
220 - (web::NavigationItemList)items {
221 return [self itemListForEntryList:self.entries];
222 }
223
224 - (NSUInteger)itemCount {
225 return self.entries.count;
226 }
227
228 - (web::NavigationItemImpl*)currentItem {
229 return self.currentEntry.navigationItemImpl;
230 }
231
232 - (web::NavigationItemImpl*)visibleItem {
233 return self.visibleEntry.navigationItemImpl;
234 }
235
236 - (web::NavigationItemImpl*)pendingItem {
237 return self.pendingEntry.navigationItemImpl;
238 }
239
240 - (web::NavigationItemImpl*)transientItem {
241 return self.transientEntry.navigationItemImpl;
242 }
243
244 - (web::NavigationItemImpl*)lastCommittedItem {
245 return self.lastCommittedEntry.navigationItemImpl;
246 }
247
248 - (web::NavigationItemImpl*)previousItem {
249 return self.previousEntry.navigationItemImpl;
250 }
251
252 - (web::NavigationItemImpl*)lastUserItem {
253 return self.lastUserEntry.navigationItemImpl;
254 }
255
256 - (web::NavigationItemList)backwardItems {
257 return [self itemListForEntryList:self.backwardEntries];
258 }
259
260 - (web::NavigationItemList)forwardItems {
261 return [self itemListForEntryList:self.forwardEntries];
262 }
263
264 // Returns the current entry in the session list, or the pending entry if there
265 // is a navigation in progress.
266 - (CRWSessionEntry*)currentEntry {
267 if (_transientEntry)
268 return _transientEntry.get();
269 if (_pendingEntry)
270 return _pendingEntry.get();
271 return [self lastCommittedEntry];
272 }
273
274 // See NavigationController::GetVisibleEntry for the motivation for this
275 // distinction.
276 - (CRWSessionEntry*)visibleEntry {
277 if (_transientEntry)
278 return _transientEntry.get();
279 // Only return the pending_entry for new (non-history), browser-initiated
280 // navigations in order to prevent URL spoof attacks.
281 web::NavigationItemImpl* pendingItem = [_pendingEntry navigationItemImpl];
282
283 if (pendingItem) {
284 bool isUserInitiated = pendingItem->NavigationInitiationType() ==
285 web::NavigationInitiationType::USER_INITIATED;
286 bool safeToShowPending = isUserInitiated && _pendingItemIndex == -1;
287
288 if (safeToShowPending)
289 return _pendingEntry.get();
290 }
291
292 return [self lastCommittedEntry];
293 }
294
295 - (CRWSessionEntry*)pendingEntry {
296 return _pendingEntry.get();
297 }
298
299 - (CRWSessionEntry*)transientEntry {
300 return _transientEntry.get();
301 }
302
303 - (CRWSessionEntry*)lastCommittedEntry {
304 if (_currentNavigationIndex == -1)
305 return nil;
306 return [_entries objectAtIndex:_currentNavigationIndex];
307 }
308
309 // Returns the previous entry in the session list, or nil if there isn't any.
310 - (CRWSessionEntry*)previousEntry {
311 if ((_previousNavigationIndex < 0) || (![_entries count]))
312 return nil;
313 return [_entries objectAtIndex:_previousNavigationIndex];
314 }
315
316 - (void)addPendingItem:(const GURL&)url 315 - (void)addPendingItem:(const GURL&)url
317 referrer:(const web::Referrer&)ref 316 referrer:(const web::Referrer&)ref
318 transition:(ui::PageTransition)trans 317 transition:(ui::PageTransition)trans
319 initiationType:(web::NavigationInitiationType)initiationType { 318 initiationType:(web::NavigationInitiationType)initiationType {
320 [self discardTransientItem]; 319 [self discardTransientItem];
321 _pendingItemIndex = -1; 320 self.pendingItemIndex = -1;
322 321
323 // Don't create a new entry if it's already the same as the current entry, 322 // Don't create a new item if it's already the same as the current item,
324 // allowing this routine to be called multiple times in a row without issue. 323 // allowing this routine to be called multiple times in a row without issue.
325 // Note: CRWSessionController currently has the responsibility to distinguish 324 // Note: CRWSessionController currently has the responsibility to distinguish
326 // between new navigations and history stack navigation, hence the inclusion 325 // between new navigations and history stack navigation, hence the inclusion
327 // of specific transiton type logic here, in order to make it reliable with 326 // of specific transiton type logic here, in order to make it reliable with
328 // real-world observed behavior. 327 // real-world observed behavior.
329 // TODO(crbug.com/676129): Fix the way changes are detected/reported elsewhere 328 // TODO(crbug.com/676129): Fix the way changes are detected/reported elsewhere
330 // in the web layer so that this hack can be removed. 329 // in the web layer so that this hack can be removed.
331 // Remove the workaround code from -presentSafeBrowsingWarningForResource:. 330 // Remove the workaround code from -presentSafeBrowsingWarningForResource:.
332 CRWSessionEntry* currentEntry = self.currentEntry; 331 web::NavigationItemImpl* currentItem = self.currentItem;
333 if (currentEntry) { 332 if (currentItem) {
334 web::NavigationItem* item = [currentEntry navigationItem]; 333 BOOL hasSameURL = currentItem->GetURL() == url;
335
336 BOOL hasSameURL = item->GetURL() == url;
337 BOOL isPendingTransitionFormSubmit = 334 BOOL isPendingTransitionFormSubmit =
338 PageTransitionCoreTypeIs(trans, ui::PAGE_TRANSITION_FORM_SUBMIT); 335 PageTransitionCoreTypeIs(trans, ui::PAGE_TRANSITION_FORM_SUBMIT);
339 BOOL isCurrentTransitionFormSubmit = PageTransitionCoreTypeIs( 336 BOOL isCurrentTransitionFormSubmit = PageTransitionCoreTypeIs(
340 item->GetTransitionType(), ui::PAGE_TRANSITION_FORM_SUBMIT); 337 currentItem->GetTransitionType(), ui::PAGE_TRANSITION_FORM_SUBMIT);
341 BOOL shouldCreatePendingItem = 338 BOOL shouldCreatePendingItem =
342 !hasSameURL || 339 !hasSameURL ||
343 (isPendingTransitionFormSubmit && !isCurrentTransitionFormSubmit); 340 (isPendingTransitionFormSubmit && !isCurrentTransitionFormSubmit);
344 341
345 if (!shouldCreatePendingItem) { 342 if (!shouldCreatePendingItem) {
346 // Send the notification anyway, to preserve old behavior. It's unknown 343 // Send the notification anyway, to preserve old behavior. It's unknown
347 // whether anything currently relies on this, but since both this whole 344 // whether anything currently relies on this, but since both this whole
348 // hack and the content facade will both be going away, it's not worth 345 // hack and the content facade will both be going away, it's not worth
349 // trying to unwind. 346 // trying to unwind.
350 if (_navigationManager && _navigationManager->GetFacadeDelegate()) { 347 if (_navigationManager && _navigationManager->GetFacadeDelegate())
351 _navigationManager->GetFacadeDelegate()->OnNavigationItemPending(); 348 _navigationManager->GetFacadeDelegate()->OnNavigationItemPending();
352 }
353 return; 349 return;
354 } 350 }
355 } 351 }
356 352
357 _pendingEntry.reset([self sessionEntryWithURL:url 353 _pendingItem = [self itemWithURL:url
358 referrer:ref 354 referrer:ref
359 transition:trans 355 transition:trans
360 initiationType:initiationType]); 356 initiationType:initiationType];
361 357
362 if (_navigationManager && _navigationManager->GetFacadeDelegate()) { 358 if (_navigationManager && _navigationManager->GetFacadeDelegate())
363 _navigationManager->GetFacadeDelegate()->OnNavigationItemPending(); 359 _navigationManager->GetFacadeDelegate()->OnNavigationItemPending();
364 }
365 } 360 }
366 361
367 - (void)updatePendingItem:(const GURL&)url { 362 - (void)updatePendingItem:(const GURL&)url {
368 // If there is no pending entry, navigation is probably happening within the 363 // If there is no pending item, navigation is probably happening within the
369 // session history. Don't modify the entry list. 364 // session history. Don't modify the item list.
370 if (!_pendingEntry) 365 web::NavigationItemImpl* item = self.pendingItem;
366 if (!item)
371 return; 367 return;
372 368
373 web::NavigationItemImpl* item = [_pendingEntry navigationItemImpl];
374 if (url != item->GetURL()) { 369 if (url != item->GetURL()) {
375 // Assume a redirection, and discard any transient entry. 370 // Assume a redirection, and discard any transient item.
376 // TODO(stuartmorgan): Once the current safe browsing code is gone, 371 // TODO(stuartmorgan): Once the current safe browsing code is gone,
377 // consider making this a DCHECK that there's no transient entry. 372 // consider making this a DCHECK that there's no transient item.
378 [self discardTransientItem]; 373 [self discardTransientItem];
379 374
380 item->SetURL(url); 375 item->SetURL(url);
381 item->SetVirtualURL(url); 376 item->SetVirtualURL(url);
382 // Redirects (3xx response code), or client side navigation must change 377 // Redirects (3xx response code), or client side navigation must change
383 // POST requests to GETs. 378 // POST requests to GETs.
384 item->SetPostData(nil); 379 item->SetPostData(nil);
385 item->ResetHttpRequestHeaders(); 380 item->ResetHttpRequestHeaders();
386 } 381 }
387 382
388 // This should probably not be sent if the URLs matched, but that's what was 383 // This should probably not be sent if the URLs matched, but that's what was
389 // done before, so preserve behavior in case something relies on it. 384 // done before, so preserve behavior in case something relies on it.
390 if (_navigationManager && _navigationManager->GetFacadeDelegate()) { 385 if (_navigationManager && _navigationManager->GetFacadeDelegate())
391 _navigationManager->GetFacadeDelegate()->OnNavigationItemPending(); 386 _navigationManager->GetFacadeDelegate()->OnNavigationItemPending();
392 }
393 } 387 }
394 388
395 - (void)clearForwardItems { 389 - (void)clearForwardItems {
396 DCHECK_EQ(_pendingItemIndex, -1); 390 DCHECK_EQ(self.pendingItemIndex, -1);
397 [self discardTransientItem]; 391 [self discardTransientItem];
398 392
399 NSInteger forwardItemStartIndex = _currentNavigationIndex + 1; 393 NSInteger forwardItemStartIndex = _currentNavigationIndex + 1;
400 DCHECK(forwardItemStartIndex >= 0); 394 DCHECK(forwardItemStartIndex >= 0);
401 395
402 if (forwardItemStartIndex >= static_cast<NSInteger>([_entries count])) 396 size_t itemCount = self.items.size();
397 if (forwardItemStartIndex >= static_cast<NSInteger>(itemCount))
403 return; 398 return;
404 399
405 NSRange remove = NSMakeRange(forwardItemStartIndex,
406 [_entries count] - forwardItemStartIndex);
407 // Store removed items in temporary NSArray so they can be deallocated after
408 // their facades.
409 base::scoped_nsobject<NSArray> removedItems(
410 [_entries subarrayWithRange:remove]);
411 [_entries removeObjectsInRange:remove];
412 if (_previousNavigationIndex >= forwardItemStartIndex) 400 if (_previousNavigationIndex >= forwardItemStartIndex)
413 _previousNavigationIndex = -1; 401 _previousNavigationIndex = -1;
414 if (_navigationManager) { 402 if (_navigationManager) {
415 _navigationManager->OnNavigationItemsPruned(remove.length); 403 _navigationManager->OnNavigationItemsPruned(self.items.size() -
Eugene But (OOO till 7-30) 2017/03/09 16:10:58 Calling OnNavigationItemsPruned before removing it
kkhorimoto 2017/03/09 21:33:54 Fixed
404 forwardItemStartIndex);
416 } 405 }
406
407 // Remove the NavigationItems.
408 _items.erase(_items.begin() + forwardItemStartIndex, _items.end());
417 } 409 }
418 410
419 - (void)commitPendingItem { 411 - (void)commitPendingItem {
420 if (_pendingEntry) { 412 if (self.pendingItem) {
421 NSInteger newNavigationIndex = _pendingItemIndex; 413 // Once an item is committed it's not renderer-initiated any more. (Matches
422 if (_pendingItemIndex == -1) { 414 // the implementation in NavigationController.)
415 self.pendingItem->ResetForCommit();
416
417 NSInteger newNavigationIndex = self.pendingItemIndex;
418 if (newNavigationIndex == -1) {
423 [self clearForwardItems]; 419 [self clearForwardItems];
424 // Add the new entry at the end. 420 // Add the new item at the end.
425 [_entries addObject:_pendingEntry]; 421 _items.push_back(std::move(_pendingItem));
426 newNavigationIndex = [_entries count] - 1; 422 newNavigationIndex = self.items.size() - 1;
427 } 423 }
428 _previousNavigationIndex = _currentNavigationIndex; 424 _previousNavigationIndex = _currentNavigationIndex;
429 self.currentNavigationIndex = newNavigationIndex; 425 self.currentNavigationIndex = newNavigationIndex;
430 // Once an entry is committed it's not renderer-initiated any more. (Matches 426 self.pendingItemIndex = -1;
431 // the implementation in NavigationController.)
432 [_pendingEntry navigationItemImpl]->ResetForCommit();
433 _pendingEntry.reset();
Eugene But (OOO till 7-30) 2017/03/09 16:10:58 Do we need to clear the reference to pendingItem?
kkhorimoto 2017/03/09 21:33:54 Nope, _pendingItem only holds a pointer for non-hi
434 _pendingItemIndex = -1;
435 } 427 }
436 428
437 CRWSessionEntry* currentEntry = self.currentEntry; 429 web::NavigationItem* item = self.currentItem;
438 web::NavigationItem* item = currentEntry.navigationItem;
439 // Update the navigation timestamp now that it's actually happened. 430 // Update the navigation timestamp now that it's actually happened.
440 if (item) 431 if (item)
441 item->SetTimestamp(_timeSmoother.GetSmoothedTime(base::Time::Now())); 432 item->SetTimestamp(_timeSmoother.GetSmoothedTime(base::Time::Now()));
442 433
443 if (_navigationManager && item) 434 if (_navigationManager && item)
444 _navigationManager->OnNavigationItemCommitted(); 435 _navigationManager->OnNavigationItemCommitted();
445 DCHECK_EQ(_pendingItemIndex, -1); 436 DCHECK_EQ(self.pendingItemIndex, -1);
446 } 437 }
447 438
448 - (void)addTransientItemWithURL:(const GURL&)URL { 439 - (void)addTransientItemWithURL:(const GURL&)URL {
449 _transientEntry.reset([self 440 _transientItem =
450 sessionEntryWithURL:URL 441 [self itemWithURL:URL
451 referrer:web::Referrer() 442 referrer:web::Referrer()
452 transition:ui::PAGE_TRANSITION_CLIENT_REDIRECT 443 transition:ui::PAGE_TRANSITION_CLIENT_REDIRECT
453 initiationType:web::NavigationInitiationType::USER_INITIATED]); 444 initiationType:web::NavigationInitiationType::USER_INITIATED];
454 445 _transientItem->SetTimestamp(
455 web::NavigationItem* navigationItem = [_transientEntry navigationItem];
456 DCHECK(navigationItem);
457 navigationItem->SetTimestamp(
458 _timeSmoother.GetSmoothedTime(base::Time::Now())); 446 _timeSmoother.GetSmoothedTime(base::Time::Now()));
459 } 447 }
460 448
461 - (void)pushNewItemWithURL:(const GURL&)URL 449 - (void)pushNewItemWithURL:(const GURL&)URL
462 stateObject:(NSString*)stateObject 450 stateObject:(NSString*)stateObject
463 transition:(ui::PageTransition)transition { 451 transition:(ui::PageTransition)transition {
464 DCHECK(![self pendingEntry]); 452 DCHECK(!self.pendingItem);
465 DCHECK([self currentEntry]); 453 DCHECK(self.currentItem);
466 454
467 web::NavigationItem* lastCommittedItem = 455 web::NavigationItem* lastCommittedItem = self.lastCommittedItem;
468 self.lastCommittedEntry.navigationItem;
469 CHECK(web::history_state_util::IsHistoryStateChangeValid( 456 CHECK(web::history_state_util::IsHistoryStateChangeValid(
470 lastCommittedItem->GetURL(), URL)); 457 lastCommittedItem->GetURL(), URL));
471 458
472 web::Referrer referrer(lastCommittedItem->GetURL(), 459 web::Referrer referrer(lastCommittedItem->GetURL(),
473 web::ReferrerPolicyDefault); 460 web::ReferrerPolicyDefault);
474 base::scoped_nsobject<CRWSessionEntry> pushedEntry([self 461 std::unique_ptr<web::NavigationItemImpl> pushedItem =
475 sessionEntryWithURL:URL 462 [self itemWithURL:URL
476 referrer:referrer 463 referrer:referrer
477 transition:transition 464 transition:transition
478 initiationType:web::NavigationInitiationType::USER_INITIATED]); 465 initiationType:web::NavigationInitiationType::USER_INITIATED];
479
480 web::NavigationItemImpl* pushedItem = [pushedEntry navigationItemImpl];
481 pushedItem->SetUserAgentType(lastCommittedItem->GetUserAgentType()); 466 pushedItem->SetUserAgentType(lastCommittedItem->GetUserAgentType());
482 pushedItem->SetSerializedStateObject(stateObject); 467 pushedItem->SetSerializedStateObject(stateObject);
483 pushedItem->SetIsCreatedFromPushState(true); 468 pushedItem->SetIsCreatedFromPushState(true);
484 pushedItem->GetSSL() = lastCommittedItem->GetSSL(); 469 pushedItem->GetSSL() = lastCommittedItem->GetSSL();
485 pushedItem->SetTimestamp(_timeSmoother.GetSmoothedTime(base::Time::Now())); 470 pushedItem->SetTimestamp(_timeSmoother.GetSmoothedTime(base::Time::Now()));
486 471
487 [self clearForwardItems]; 472 [self clearForwardItems];
488 // Add the new entry at the end. 473 // Add the new item at the end.
489 [_entries addObject:pushedEntry]; 474 _items.push_back(std::move(pushedItem));
490 _previousNavigationIndex = _currentNavigationIndex; 475 _previousNavigationIndex = _currentNavigationIndex;
491 self.currentNavigationIndex = [_entries count] - 1; 476 self.currentNavigationIndex = self.items.size() - 1;
492 477
493 if (_navigationManager) 478 if (_navigationManager)
494 _navigationManager->OnNavigationItemCommitted(); 479 _navigationManager->OnNavigationItemCommitted();
495 } 480 }
496 481
497 - (void)updateCurrentItemWithURL:(const GURL&)url 482 - (void)updateCurrentItemWithURL:(const GURL&)url
498 stateObject:(NSString*)stateObject { 483 stateObject:(NSString*)stateObject {
499 DCHECK(!_transientEntry); 484 DCHECK(!self.transientItem);
500 CRWSessionEntry* currentEntry = self.currentEntry; 485 web::NavigationItemImpl* currentItem = self.currentItem;
501 web::NavigationItemImpl* currentItem = self.currentEntry.navigationItemImpl;
502 currentItem->SetURL(url); 486 currentItem->SetURL(url);
503 currentItem->SetSerializedStateObject(stateObject); 487 currentItem->SetSerializedStateObject(stateObject);
504 currentItem->SetHasStateBeenReplaced(true); 488 currentItem->SetHasStateBeenReplaced(true);
505 currentItem->SetPostData(nil); 489 currentItem->SetPostData(nil);
506 currentEntry.navigationItem->SetURL(url); 490 // If the change is to a committed item, notify interested parties.
507 // If the change is to a committed entry, notify interested parties. 491 if (currentItem != self.pendingItem && _navigationManager)
508 if (currentEntry != self.pendingEntry && _navigationManager)
509 _navigationManager->OnNavigationItemChanged(); 492 _navigationManager->OnNavigationItemChanged();
510 } 493 }
511 494
512 - (void)discardNonCommittedItems { 495 - (void)discardNonCommittedItems {
513 [self discardTransientItem]; 496 [self discardTransientItem];
514 _pendingEntry.reset(); 497 _pendingItem.reset();
515 _pendingItemIndex = -1; 498 self.pendingItemIndex = -1;
516 } 499 }
517 500
518 - (void)discardTransientItem { 501 - (void)discardTransientItem {
519 // Keep the entry alive temporarily. There are flows that get the current 502 _transientItem.reset();
520 // entry, do some navigation operation, and then try to use that old current
521 // entry; since navigations clear the transient entry, these flows might
522 // crash. (This should be removable once more session management is handled
523 // within this class and/or NavigationManager).
524 _transientEntry.reset();
525 } 503 }
526 504
527 - (void)insertStateFromSessionController:(CRWSessionController*)sourceSession { 505 - (void)insertStateFromSessionController:(CRWSessionController*)sourceSession {
528 DCHECK(sourceSession); 506 DCHECK(sourceSession);
529 // The other session may not have any entries, in which case there is nothing 507
530 // to insert. The other session's currentNavigationEntry will be bogus 508 // The other session may not have any items, in which case there is nothing
531 // in such cases, so ignore it and return early. 509 // to insert. The other session's currentItem will be bogus in such cases, so
532 NSArray* sourceEntries = sourceSession.entries; 510 // ignore it and return early.
533 if (!sourceEntries.count) 511 web::ScopedNavigationItemImplList& sourceItems = sourceSession->_items;
512 if (sourceItems.empty())
534 return; 513 return;
535 514
536 // Cycle through the entries from the other session and insert them before any 515 // Cycle through the items from the other session and insert them before any
537 // entries from this session. Do not copy anything that comes after the other 516 // items from this session. Do not copy anything that comes after the other
538 // session's current entry. 517 // session's current item.
539 NSInteger lastIndexToCopy = sourceSession.currentNavigationIndex; 518 NSInteger lastIndexToCopy = sourceSession.currentNavigationIndex;
540 for (NSInteger i = 0; i <= lastIndexToCopy; ++i) { 519 for (NSInteger i = 0; i <= lastIndexToCopy; ++i) {
541 [_entries insertObject:sourceEntries[i] atIndex:i]; 520 std::unique_ptr<web::NavigationItemImpl> sourceItemCopy(
521 new web::NavigationItemImpl(*sourceItems[i].get()));
Eugene But (OOO till 7-30) 2017/03/09 16:10:58 nit: s/new/base::MakeUnique
kkhorimoto 2017/03/09 21:33:54 Done.
522 _items.insert(_items.begin() + i, std::move(sourceItemCopy));
542 } 523 }
543 524
525 // Update state to reflect inserted NavigationItems.
544 _previousNavigationIndex = -1; 526 _previousNavigationIndex = -1;
545 _currentNavigationIndex += lastIndexToCopy + 1; 527 _currentNavigationIndex += lastIndexToCopy + 1;
546 if (_pendingItemIndex != -1) 528 if (self.pendingItemIndex != -1)
547 _pendingItemIndex += lastIndexToCopy + 1; 529 self.pendingItemIndex += lastIndexToCopy + 1;
548 530
549 DCHECK_LT(static_cast<NSUInteger>(_currentNavigationIndex), _entries.count); 531 DCHECK_LT(static_cast<NSUInteger>(_currentNavigationIndex),
550 DCHECK(_pendingItemIndex == -1 || _pendingEntry); 532 self.items.size());
533 DCHECK(self.pendingItemIndex == -1 || self.pendingItem);
551 } 534 }
552 535
553 - (void)goToItemAtIndex:(NSInteger)index { 536 - (void)goToItemAtIndex:(NSInteger)index {
554 if (index < 0 || static_cast<NSUInteger>(index) >= _entries.count) 537 if (index < 0 || static_cast<NSUInteger>(index) >= self.items.size())
555 return; 538 return;
556 539
557 if (index < _currentNavigationIndex) { 540 if (index < _currentNavigationIndex) {
558 // Going back. 541 // Going back.
559 [self discardNonCommittedItems]; 542 [self discardNonCommittedItems];
560 } else if (_currentNavigationIndex < index) { 543 } else if (_currentNavigationIndex < index) {
561 // Going forward. 544 // Going forward.
562 [self discardTransientItem]; 545 [self discardTransientItem];
563 } else { 546 } else {
564 // |delta| is 0, no need to change current navigation index. 547 // |delta| is 0, no need to change current navigation index.
565 return; 548 return;
566 } 549 }
567 550
568 _previousNavigationIndex = _currentNavigationIndex; 551 _previousNavigationIndex = _currentNavigationIndex;
569 _currentNavigationIndex = index; 552 _currentNavigationIndex = index;
570 } 553 }
571 554
572 - (void)removeItemAtIndex:(NSInteger)index { 555 - (void)removeItemAtIndex:(NSInteger)index {
573 DCHECK(index < static_cast<NSInteger>([_entries count])); 556 DCHECK(index < static_cast<NSInteger>(self.items.size()));
574 DCHECK(index != _currentNavigationIndex); 557 DCHECK(index != _currentNavigationIndex);
575 DCHECK(index >= 0); 558 DCHECK(index >= 0);
576 559
577 [self discardNonCommittedItems]; 560 [self discardNonCommittedItems];
578 561
579 [_entries removeObjectAtIndex:index]; 562 _items.erase(_items.begin() + index);
580 if (_currentNavigationIndex > index) 563 if (_currentNavigationIndex > index)
581 _currentNavigationIndex--; 564 _currentNavigationIndex--;
582 if (_previousNavigationIndex >= index) 565 if (_previousNavigationIndex >= index)
583 _previousNavigationIndex--; 566 _previousNavigationIndex--;
584 } 567 }
585 568
586 - (NSArray*)backwardEntries {
587 NSMutableArray* entries = [NSMutableArray array];
588 for (NSInteger index = _currentNavigationIndex; index > 0; --index) {
589 if (![self isRedirectTransitionForItemAtIndex:index])
590 [entries addObject:_entries[index - 1]];
591 }
592 return entries;
593 }
594
595 - (NSArray*)forwardEntries {
596 NSMutableArray* entries = [NSMutableArray array];
597 NSUInteger lastNonRedirectedIndex = _currentNavigationIndex + 1;
598 while (lastNonRedirectedIndex < [_entries count]) {
599 CRWSessionEntry* entry = [_entries objectAtIndex:lastNonRedirectedIndex];
600 if (!ui::PageTransitionIsRedirect(
601 entry.navigationItem->GetTransitionType())) {
602 [entries addObject:entry];
603 }
604 ++lastNonRedirectedIndex;
605 }
606 return entries;
607 }
608
609 - (BOOL)isSameDocumentNavigationBetweenItem:(web::NavigationItem*)firstItem 569 - (BOOL)isSameDocumentNavigationBetweenItem:(web::NavigationItem*)firstItem
610 andItem:(web::NavigationItem*)secondItem { 570 andItem:(web::NavigationItem*)secondItem {
611 if (!firstItem || !secondItem || firstItem == secondItem) 571 if (!firstItem || !secondItem || firstItem == secondItem)
612 return NO; 572 return NO;
613 NSUInteger firstIndex = [self indexOfItem:firstItem]; 573 NSUInteger firstIndex = [self indexOfItem:firstItem];
614 NSUInteger secondIndex = [self indexOfItem:secondItem]; 574 NSUInteger secondIndex = [self indexOfItem:secondItem];
615 if (firstIndex == NSNotFound || secondIndex == NSNotFound) 575 if (firstIndex == NSNotFound || secondIndex == NSNotFound)
616 return NO; 576 return NO;
617 NSUInteger startIndex = firstIndex < secondIndex ? firstIndex : secondIndex; 577 NSUInteger startIndex = firstIndex < secondIndex ? firstIndex : secondIndex;
618 NSUInteger endIndex = firstIndex < secondIndex ? secondIndex : firstIndex; 578 NSUInteger endIndex = firstIndex < secondIndex ? secondIndex : firstIndex;
619 579
620 for (NSUInteger i = startIndex + 1; i <= endIndex; i++) { 580 for (NSUInteger i = startIndex + 1; i <= endIndex; i++) {
621 web::NavigationItemImpl* item = [_entries[i] navigationItemImpl]; 581 web::NavigationItemImpl* item = self.items[i].get();
622 // Every entry in the sequence has to be created from a hash change or 582 // Every item in the sequence has to be created from a hash change or
623 // pushState() call. 583 // pushState() call.
624 if (!item->IsCreatedFromPushState() && !item->IsCreatedFromHashChange()) 584 if (!item->IsCreatedFromPushState() && !item->IsCreatedFromHashChange())
625 return NO; 585 return NO;
626 // Every entry in the sequence has to have a URL that could have been 586 // Every item in the sequence has to have a URL that could have been
627 // created from a pushState() call. 587 // created from a pushState() call.
628 if (!web::history_state_util::IsHistoryStateChangeValid(firstItem->GetURL(), 588 if (!web::history_state_util::IsHistoryStateChangeValid(firstItem->GetURL(),
629 item->GetURL())) 589 item->GetURL()))
630 return NO; 590 return NO;
631 } 591 }
632 return YES; 592 return YES;
633 } 593 }
634 594
635 - (CRWSessionEntry*)lastUserEntry {
636 if (![_entries count])
637 return nil;
638
639 NSInteger index = _currentNavigationIndex;
640 // This will return the first session entry if all other entries are
641 // redirects, regardless of the transition state of the first entry.
642 while (index > 0 && [self isRedirectTransitionForItemAtIndex:index]) {
643 --index;
644 }
645 return [_entries objectAtIndex:index];
646 }
647
648 - (NSInteger)indexOfItem:(const web::NavigationItem*)item { 595 - (NSInteger)indexOfItem:(const web::NavigationItem*)item {
649 for (NSUInteger index = 0; index < self.entries.count; ++index) { 596 DCHECK(item);
650 if ([self.entries[index] navigationItem] == item) 597 for (size_t index = 0; index < self.items.size(); ++index) {
651 return static_cast<NSInteger>(index); 598 if (self.items[index].get() == item)
599 return index;
652 } 600 }
653 return NSNotFound; 601 return NSNotFound;
654 } 602 }
655 603
656 - (web::NavigationItemImpl*)itemAtIndex:(NSInteger)index { 604 - (web::NavigationItemImpl*)itemAtIndex:(NSInteger)index {
657 if (index < 0 || self.entries.count <= static_cast<NSUInteger>(index)) 605 if (index < 0 || self.items.size() <= static_cast<NSUInteger>(index))
658 return nullptr; 606 return nullptr;
659 return static_cast<web::NavigationItemImpl*>( 607 return self.items[index].get();
660 [self.entries[index] navigationItem]);
661 } 608 }
662 609
663 #pragma mark - 610 #pragma mark -
664 #pragma mark Private methods 611 #pragma mark Private methods
665 612
666 - (CRWSessionEntry*)sessionEntryWithURL:(const GURL&)url 613 - (std::unique_ptr<web::NavigationItemImpl>)
667 referrer:(const web::Referrer&)referrer 614 itemWithURL:(const GURL&)url
668 transition:(ui::PageTransition)transition 615 referrer:(const web::Referrer&)referrer
669 initiationType: 616 transition:(ui::PageTransition)transition
670 (web::NavigationInitiationType)initiationType { 617 initiationType:(web::NavigationInitiationType)initiationType {
671 GURL loaded_url(url); 618 GURL loaded_url(url);
672 BOOL urlWasRewritten = NO; 619 BOOL urlWasRewritten = NO;
673 if (_navigationManager) { 620 if (_navigationManager) {
674 std::unique_ptr<std::vector<web::BrowserURLRewriter::URLRewriter>> 621 std::unique_ptr<std::vector<web::BrowserURLRewriter::URLRewriter>>
675 transientRewriters = _navigationManager->GetTransientURLRewriters(); 622 transientRewriters = _navigationManager->GetTransientURLRewriters();
676 if (transientRewriters) { 623 if (transientRewriters) {
677 urlWasRewritten = web::BrowserURLRewriter::RewriteURLWithWriters( 624 urlWasRewritten = web::BrowserURLRewriter::RewriteURLWithWriters(
678 &loaded_url, _browserState, *transientRewriters.get()); 625 &loaded_url, _browserState, *transientRewriters.get());
679 } 626 }
680 } 627 }
681 if (!urlWasRewritten) { 628 if (!urlWasRewritten) {
682 web::BrowserURLRewriter::GetInstance()->RewriteURLIfNecessary( 629 web::BrowserURLRewriter::GetInstance()->RewriteURLIfNecessary(
683 &loaded_url, _browserState); 630 &loaded_url, _browserState);
684 } 631 }
685 632
686 std::unique_ptr<web::NavigationItemImpl> item(new web::NavigationItemImpl()); 633 std::unique_ptr<web::NavigationItemImpl> item(new web::NavigationItemImpl());
687 item->SetOriginalRequestURL(loaded_url); 634 item->SetOriginalRequestURL(loaded_url);
688 item->SetURL(loaded_url); 635 item->SetURL(loaded_url);
689 item->SetReferrer(referrer); 636 item->SetReferrer(referrer);
690 item->SetTransitionType(transition); 637 item->SetTransitionType(transition);
691 item->SetNavigationInitiationType(initiationType); 638 item->SetNavigationInitiationType(initiationType);
692 if (web::GetWebClient()->IsAppSpecificURL(loaded_url)) 639 if (web::GetWebClient()->IsAppSpecificURL(loaded_url))
693 item->SetUserAgentType(web::UserAgentType::NONE); 640 item->SetUserAgentType(web::UserAgentType::NONE);
694 return [[CRWSessionEntry alloc] initWithNavigationItem:std::move(item)]; 641 return item;
695 } 642 }
696 643
697 - (BOOL)isRedirectTransitionForItemAtIndex:(NSInteger)index { 644 - (BOOL)isRedirectTransitionForItemAtIndex:(size_t)index {
698 ui::PageTransition transition = 645 DCHECK_LT(index, self.items.size());
699 [_entries[index] navigationItem]->GetTransitionType(); 646 ui::PageTransition transition = self.items[index]->GetTransitionType();
700 return (transition & ui::PAGE_TRANSITION_IS_REDIRECT_MASK) ? YES : NO; 647 return (transition & ui::PAGE_TRANSITION_IS_REDIRECT_MASK) ? YES : NO;
701 } 648 }
702 649
703 - (web::NavigationItemList)itemListForEntryList:(NSArray*)entries {
704 web::NavigationItemList list(entries.count);
705 for (size_t index = 0; index < entries.count; ++index)
706 list[index] = [entries[index] navigationItem];
707 return list;
708 }
709
710 @end 650 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698