OLD | NEW |
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 <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/format_macros.h" | 10 #include "base/format_macros.h" |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 _browserState = browserState; | 177 _browserState = browserState; |
178 | 178 |
179 // Create entries array from list of navigations. | 179 // Create entries array from list of navigations. |
180 _entries = [[NSMutableArray alloc] initWithCapacity:scoped_items.size()]; | 180 _entries = [[NSMutableArray alloc] initWithCapacity:scoped_items.size()]; |
181 std::vector<web::NavigationItem*> items; | 181 std::vector<web::NavigationItem*> items; |
182 scoped_items.release(&items); | 182 scoped_items.release(&items); |
183 | 183 |
184 for (size_t i = 0; i < items.size(); ++i) { | 184 for (size_t i = 0; i < items.size(); ++i) { |
185 scoped_ptr<web::NavigationItem> item(items[i]); | 185 scoped_ptr<web::NavigationItem> item(items[i]); |
186 base::scoped_nsobject<CRWSessionEntry> entry( | 186 base::scoped_nsobject<CRWSessionEntry> entry( |
187 [[CRWSessionEntry alloc] initWithNavigationItem:item.Pass() index:i]); | 187 [[CRWSessionEntry alloc] initWithNavigationItem:item.Pass()]); |
188 [_entries addObject:entry]; | 188 [_entries addObject:entry]; |
189 } | 189 } |
190 _currentNavigationIndex = currentIndex; | 190 _currentNavigationIndex = currentIndex; |
191 // Prior to M34, 0 was used as "no index" instead of -1; adjust for that. | 191 // Prior to M34, 0 was used as "no index" instead of -1; adjust for that. |
192 if (![_entries count]) | 192 if (![_entries count]) |
193 _currentNavigationIndex = -1; | 193 _currentNavigationIndex = -1; |
194 if (_currentNavigationIndex >= static_cast<NSInteger>(items.size())) { | 194 if (_currentNavigationIndex >= static_cast<NSInteger>(items.size())) { |
195 _currentNavigationIndex = static_cast<NSInteger>(items.size()) - 1; | 195 _currentNavigationIndex = static_cast<NSInteger>(items.size()) - 1; |
196 } | 196 } |
197 _previousNavigationIndex = -1; | 197 _previousNavigationIndex = -1; |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 | 319 |
320 // See NavigationController::GetVisibleEntry for the motivation for this | 320 // See NavigationController::GetVisibleEntry for the motivation for this |
321 // distinction. | 321 // distinction. |
322 - (CRWSessionEntry*)visibleEntry { | 322 - (CRWSessionEntry*)visibleEntry { |
323 if (_transientEntry) | 323 if (_transientEntry) |
324 return _transientEntry.get(); | 324 return _transientEntry.get(); |
325 // Only return the pending_entry for: | 325 // Only return the pending_entry for: |
326 // (a) new (non-history), browser-initiated navigations, and | 326 // (a) new (non-history), browser-initiated navigations, and |
327 // (b) pending unsafe navigations (while showing the interstitial) | 327 // (b) pending unsafe navigations (while showing the interstitial) |
328 // in order to prevent URL spoof attacks. | 328 // in order to prevent URL spoof attacks. |
329 web::NavigationItemImpl* pendingItemImpl = | 329 web::NavigationItemImpl* pendingItem = [_pendingEntry navigationItemImpl]; |
330 static_cast<web::NavigationItemImpl*>([_pendingEntry navigationItem]); | 330 if (pendingItem && |
331 if (_pendingEntry && | 331 (!pendingItem->is_renderer_initiated() || pendingItem->IsUnsafe())) { |
332 (!pendingItemImpl->is_renderer_initiated() || | |
333 pendingItemImpl->IsUnsafe())) { | |
334 return _pendingEntry.get(); | 332 return _pendingEntry.get(); |
335 } | 333 } |
336 return [self lastCommittedEntry]; | 334 return [self lastCommittedEntry]; |
337 } | 335 } |
338 | 336 |
339 - (CRWSessionEntry*)pendingEntry { | 337 - (CRWSessionEntry*)pendingEntry { |
340 return _pendingEntry.get(); | 338 return _pendingEntry.get(); |
341 } | 339 } |
342 | 340 |
343 - (CRWSessionEntry*)transientEntry { | 341 - (CRWSessionEntry*)transientEntry { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 // whether anything currently relies on this, but since both this whole | 388 // whether anything currently relies on this, but since both this whole |
391 // hack and the content facade will both be going away, it's not worth | 389 // hack and the content facade will both be going away, it's not worth |
392 // trying to unwind. | 390 // trying to unwind. |
393 if (_navigationManager && _navigationManager->GetFacadeDelegate()) { | 391 if (_navigationManager && _navigationManager->GetFacadeDelegate()) { |
394 _navigationManager->GetFacadeDelegate()->OnNavigationItemPending(); | 392 _navigationManager->GetFacadeDelegate()->OnNavigationItemPending(); |
395 } | 393 } |
396 return; | 394 return; |
397 } | 395 } |
398 } | 396 } |
399 | 397 |
400 BOOL useDesktopUserAgent = _useDesktopUserAgentForNextPendingEntry || | 398 BOOL useDesktopUserAgent = |
401 self.currentEntry.useDesktopUserAgent; | 399 _useDesktopUserAgentForNextPendingEntry || |
| 400 (self.currentEntry.navigationItem && |
| 401 self.currentEntry.navigationItem->IsOverridingUserAgent()); |
402 _useDesktopUserAgentForNextPendingEntry = NO; | 402 _useDesktopUserAgentForNextPendingEntry = NO; |
403 _pendingEntry.reset([[self sessionEntryWithURL:url | 403 _pendingEntry.reset([[self sessionEntryWithURL:url |
404 referrer:ref | 404 referrer:ref |
405 transition:trans | 405 transition:trans |
406 useDesktopUserAgent:useDesktopUserAgent | 406 useDesktopUserAgent:useDesktopUserAgent |
407 rendererInitiated:rendererInitiated] retain]); | 407 rendererInitiated:rendererInitiated] retain]); |
408 | 408 |
409 if (_navigationManager && _navigationManager->GetFacadeDelegate()) { | 409 if (_navigationManager && _navigationManager->GetFacadeDelegate()) { |
410 _navigationManager->GetFacadeDelegate()->OnNavigationItemPending(); | 410 _navigationManager->GetFacadeDelegate()->OnNavigationItemPending(); |
411 } | 411 } |
412 } | 412 } |
413 | 413 |
414 - (void)updatePendingEntry:(const GURL&)url { | 414 - (void)updatePendingEntry:(const GURL&)url { |
415 [self discardTransientEntry]; | 415 [self discardTransientEntry]; |
416 | 416 |
417 // If there is no pending entry, navigation is probably happening within the | 417 // If there is no pending entry, navigation is probably happening within the |
418 // session history. Don't modify the entry list. | 418 // session history. Don't modify the entry list. |
419 if (!_pendingEntry) | 419 if (!_pendingEntry) |
420 return; | 420 return; |
421 web::NavigationItem* item = [_pendingEntry navigationItem]; | 421 |
| 422 web::NavigationItemImpl* item = [_pendingEntry navigationItemImpl]; |
422 if (url != item->GetURL()) { | 423 if (url != item->GetURL()) { |
423 item->SetURL(url); | 424 item->SetURL(url); |
424 item->SetVirtualURL(url); | 425 item->SetVirtualURL(url); |
425 // Since updates are caused by page redirects, they are renderer-initiated. | 426 // Since updates are caused by page redirects, they are renderer-initiated. |
426 web::NavigationItemImpl* pendingItemImpl = | 427 item->set_is_renderer_initiated(true); |
427 static_cast<web::NavigationItemImpl*>([_pendingEntry navigationItem]); | |
428 pendingItemImpl->set_is_renderer_initiated(true); | |
429 // Redirects (3xx response code), or client side navigation must change | 428 // Redirects (3xx response code), or client side navigation must change |
430 // POST requests to GETs. | 429 // POST requests to GETs. |
431 [_pendingEntry setPOSTData:nil]; | 430 item->SetPostData(nil); |
432 [_pendingEntry resetHTTPHeaders]; | 431 item->ResetHttpRequestHeaders(); |
433 } | 432 } |
434 | 433 |
435 // This should probably not be sent if the URLs matched, but that's what was | 434 // This should probably not be sent if the URLs matched, but that's what was |
436 // done before, so preserve behavior in case something relies on it. | 435 // done before, so preserve behavior in case something relies on it. |
437 if (_navigationManager && _navigationManager->GetFacadeDelegate()) { | 436 if (_navigationManager && _navigationManager->GetFacadeDelegate()) { |
438 _navigationManager->GetFacadeDelegate()->OnNavigationItemPending(); | 437 _navigationManager->GetFacadeDelegate()->OnNavigationItemPending(); |
439 } | 438 } |
440 } | 439 } |
441 | 440 |
442 - (void)clearForwardEntries { | 441 - (void)clearForwardEntries { |
(...skipping 22 matching lines...) Expand all Loading... |
465 | 464 |
466 - (void)commitPendingEntry { | 465 - (void)commitPendingEntry { |
467 if (_pendingEntry) { | 466 if (_pendingEntry) { |
468 [self clearForwardEntries]; | 467 [self clearForwardEntries]; |
469 // Add the new entry at the end. | 468 // Add the new entry at the end. |
470 [_entries addObject:_pendingEntry]; | 469 [_entries addObject:_pendingEntry]; |
471 _previousNavigationIndex = _currentNavigationIndex; | 470 _previousNavigationIndex = _currentNavigationIndex; |
472 _currentNavigationIndex = [_entries count] - 1; | 471 _currentNavigationIndex = [_entries count] - 1; |
473 // Once an entry is committed it's not renderer-initiated any more. (Matches | 472 // Once an entry is committed it's not renderer-initiated any more. (Matches |
474 // the implementation in NavigationController.) | 473 // the implementation in NavigationController.) |
475 web::NavigationItemImpl* pendingItemImpl = | 474 [_pendingEntry navigationItemImpl]->ResetForCommit(); |
476 static_cast<web::NavigationItemImpl*>([_pendingEntry navigationItem]); | |
477 pendingItemImpl->ResetForCommit(); | |
478 _pendingEntry.reset(); | 475 _pendingEntry.reset(); |
479 } | 476 } |
480 | 477 |
481 CRWSessionEntry* currentEntry = self.currentEntry; | 478 CRWSessionEntry* currentEntry = self.currentEntry; |
482 web::NavigationItem* item = currentEntry.navigationItem; | 479 web::NavigationItem* item = currentEntry.navigationItem; |
483 // Update the navigation timestamp now that it's actually happened. | 480 // Update the navigation timestamp now that it's actually happened. |
484 if (item) | 481 if (item) |
485 item->SetTimestamp(_timeSmoother.GetSmoothedTime(base::Time::Now())); | 482 item->SetTimestamp(_timeSmoother.GetSmoothedTime(base::Time::Now())); |
486 | 483 |
487 if (_navigationManager && item) | 484 if (_navigationManager && item) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 _navigationManager->OnNavigationItemChanged(); | 516 _navigationManager->OnNavigationItemChanged(); |
520 } | 517 } |
521 | 518 |
522 - (void)pushNewEntryWithURL:(const GURL&)url | 519 - (void)pushNewEntryWithURL:(const GURL&)url |
523 stateObject:(NSString*)stateObject { | 520 stateObject:(NSString*)stateObject { |
524 DCHECK([self currentEntry]); | 521 DCHECK([self currentEntry]); |
525 web::NavigationItem* item = [self currentEntry].navigationItem; | 522 web::NavigationItem* item = [self currentEntry].navigationItem; |
526 CHECK( | 523 CHECK( |
527 web::history_state_util::IsHistoryStateChangeValid(item->GetURL(), url)); | 524 web::history_state_util::IsHistoryStateChangeValid(item->GetURL(), url)); |
528 web::Referrer referrer(item->GetURL(), web::ReferrerPolicyDefault); | 525 web::Referrer referrer(item->GetURL(), web::ReferrerPolicyDefault); |
| 526 bool overrideUserAgent = |
| 527 self.currentEntry.navigationItem->IsOverridingUserAgent(); |
529 base::scoped_nsobject<CRWSessionEntry> pushedEntry( | 528 base::scoped_nsobject<CRWSessionEntry> pushedEntry( |
530 [[self sessionEntryWithURL:url | 529 [[self sessionEntryWithURL:url |
531 referrer:referrer | 530 referrer:referrer |
532 transition:ui::PAGE_TRANSITION_LINK | 531 transition:ui::PAGE_TRANSITION_LINK |
533 useDesktopUserAgent:self.currentEntry.useDesktopUserAgent | 532 useDesktopUserAgent:overrideUserAgent |
534 rendererInitiated:NO] retain]); | 533 rendererInitiated:NO] retain]); |
535 pushedEntry.get().serializedStateObject = stateObject; | 534 web::NavigationItemImpl* pushedItem = [pushedEntry navigationItemImpl]; |
536 pushedEntry.get().createdFromPushState = YES; | 535 pushedItem->SetSerializedStateObject(stateObject); |
| 536 pushedItem->SetIsCreatedFromPushState(true); |
537 web::SSLStatus& sslStatus = [self currentEntry].navigationItem->GetSSL(); | 537 web::SSLStatus& sslStatus = [self currentEntry].navigationItem->GetSSL(); |
538 pushedEntry.get().navigationItem->GetSSL() = sslStatus; | 538 pushedEntry.get().navigationItem->GetSSL() = sslStatus; |
539 | 539 |
540 [self clearForwardEntries]; | 540 [self clearForwardEntries]; |
541 // Add the new entry at the end. | 541 // Add the new entry at the end. |
542 [_entries addObject:pushedEntry]; | 542 [_entries addObject:pushedEntry]; |
543 _previousNavigationIndex = _currentNavigationIndex; | 543 _previousNavigationIndex = _currentNavigationIndex; |
544 _currentNavigationIndex = [_entries count] - 1; | 544 _currentNavigationIndex = [_entries count] - 1; |
545 | 545 |
546 if (_navigationManager) | 546 if (_navigationManager) |
547 _navigationManager->OnNavigationItemCommitted(); | 547 _navigationManager->OnNavigationItemCommitted(); |
548 } | 548 } |
549 | 549 |
550 - (void)updateCurrentEntryWithURL:(const GURL&)url | 550 - (void)updateCurrentEntryWithURL:(const GURL&)url |
551 stateObject:(NSString*)stateObject { | 551 stateObject:(NSString*)stateObject { |
552 DCHECK(!_transientEntry); | 552 DCHECK(!_transientEntry); |
553 CRWSessionEntry* currentEntry = self.currentEntry; | 553 CRWSessionEntry* currentEntry = self.currentEntry; |
| 554 web::NavigationItemImpl* currentItem = self.currentEntry.navigationItemImpl; |
| 555 currentItem->SetURL(url); |
| 556 currentItem->SetSerializedStateObject(stateObject); |
554 currentEntry.navigationItem->SetURL(url); | 557 currentEntry.navigationItem->SetURL(url); |
555 currentEntry.serializedStateObject = stateObject; | |
556 // If the change is to a committed entry, notify interested parties. | 558 // If the change is to a committed entry, notify interested parties. |
557 if (currentEntry != self.pendingEntry && _navigationManager) | 559 if (currentEntry != self.pendingEntry && _navigationManager) |
558 _navigationManager->OnNavigationItemChanged(); | 560 _navigationManager->OnNavigationItemChanged(); |
559 } | 561 } |
560 | 562 |
561 - (void)discardNonCommittedEntries { | 563 - (void)discardNonCommittedEntries { |
562 [self discardTransientEntry]; | 564 [self discardTransientEntry]; |
563 _pendingEntry.reset(); | 565 _pendingEntry.reset(); |
564 } | 566 } |
565 | 567 |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
801 if (firstEntry == secondEntry) | 803 if (firstEntry == secondEntry) |
802 return NO; | 804 return NO; |
803 NSUInteger firstIndex = [_entries indexOfObject:firstEntry]; | 805 NSUInteger firstIndex = [_entries indexOfObject:firstEntry]; |
804 NSUInteger secondIndex = [_entries indexOfObject:secondEntry]; | 806 NSUInteger secondIndex = [_entries indexOfObject:secondEntry]; |
805 if (firstIndex == NSNotFound || secondIndex == NSNotFound) | 807 if (firstIndex == NSNotFound || secondIndex == NSNotFound) |
806 return NO; | 808 return NO; |
807 NSUInteger startIndex = firstIndex < secondIndex ? firstIndex : secondIndex; | 809 NSUInteger startIndex = firstIndex < secondIndex ? firstIndex : secondIndex; |
808 NSUInteger endIndex = firstIndex < secondIndex ? secondIndex : firstIndex; | 810 NSUInteger endIndex = firstIndex < secondIndex ? secondIndex : firstIndex; |
809 | 811 |
810 for (NSUInteger i = startIndex + 1; i <= endIndex; i++) { | 812 for (NSUInteger i = startIndex + 1; i <= endIndex; i++) { |
811 CRWSessionEntry* entry = [_entries objectAtIndex:i]; | 813 web::NavigationItemImpl* item = [_entries[i] navigationItemImpl]; |
812 // Every entry in the sequence has to be created from a pushState() call. | 814 // Every entry in the sequence has to be created from a pushState() call. |
813 if (!entry.createdFromPushState) | 815 if (!item->IsCreatedFromPushState()) |
814 return NO; | 816 return NO; |
815 // Every entry in the sequence has to have a URL that could have been | 817 // Every entry in the sequence has to have a URL that could have been |
816 // created from a pushState() call. | 818 // created from a pushState() call. |
817 if (!web::history_state_util::IsHistoryStateChangeValid( | 819 if (!web::history_state_util::IsHistoryStateChangeValid( |
818 firstEntry.navigationItem->GetURL(), | 820 firstEntry.navigationItem->GetURL(), item->GetURL())) |
819 entry.navigationItem->GetURL())) | |
820 return NO; | 821 return NO; |
821 } | 822 } |
822 return YES; | 823 return YES; |
823 } | 824 } |
824 | 825 |
825 - (CRWSessionEntry*)lastUserEntry { | 826 - (CRWSessionEntry*)lastUserEntry { |
826 if (![_entries count]) | 827 if (![_entries count]) |
827 return nil; | 828 return nil; |
828 | 829 |
829 NSInteger index = _currentNavigationIndex; | 830 NSInteger index = _currentNavigationIndex; |
830 // This will return the first session entry if all other entries are | 831 // This will return the first session entry if all other entries are |
831 // redirects, regardless of the transition state of the first entry. | 832 // redirects, regardless of the transition state of the first entry. |
832 while (index > 0 && | 833 while (index > 0 && |
833 [self transitionForIndex:index] & | 834 [self transitionForIndex:index] & |
834 ui::PAGE_TRANSITION_IS_REDIRECT_MASK) { | 835 ui::PAGE_TRANSITION_IS_REDIRECT_MASK) { |
835 --index; | 836 --index; |
836 } | 837 } |
837 return [_entries objectAtIndex:index]; | 838 return [_entries objectAtIndex:index]; |
838 } | 839 } |
839 | 840 |
840 - (void)useDesktopUserAgentForNextPendingEntry { | 841 - (void)useDesktopUserAgentForNextPendingEntry { |
841 if (_pendingEntry) | 842 if (_pendingEntry) |
842 [_pendingEntry setUseDesktopUserAgent:YES]; | 843 [_pendingEntry navigationItem]->SetIsOverridingUserAgent(true); |
843 else | 844 else |
844 _useDesktopUserAgentForNextPendingEntry = YES; | 845 _useDesktopUserAgentForNextPendingEntry = YES; |
845 } | 846 } |
846 | 847 |
847 #pragma mark - | 848 #pragma mark - |
848 #pragma mark Private methods | 849 #pragma mark Private methods |
849 | 850 |
850 - (NSString*)uniqueID { | 851 - (NSString*)uniqueID { |
851 CFUUIDRef uuidRef = CFUUIDCreate(NULL); | 852 CFUUIDRef uuidRef = CFUUIDCreate(NULL); |
852 CFStringRef uuidStringRef = CFUUIDCreateString(NULL, uuidRef); | 853 CFStringRef uuidStringRef = CFUUIDCreateString(NULL, uuidRef); |
853 CFRelease(uuidRef); | 854 CFRelease(uuidRef); |
854 NSString* uuid = [NSString stringWithString:(NSString*)uuidStringRef]; | 855 NSString* uuid = [NSString stringWithString:(NSString*)uuidStringRef]; |
855 CFRelease(uuidStringRef); | 856 CFRelease(uuidStringRef); |
856 return uuid; | 857 return uuid; |
857 } | 858 } |
858 | 859 |
859 - (CRWSessionEntry*)sessionEntryWithURL:(const GURL&)url | 860 - (CRWSessionEntry*)sessionEntryWithURL:(const GURL&)url |
860 referrer:(const web::Referrer&)referrer | 861 referrer:(const web::Referrer&)referrer |
861 transition:(ui::PageTransition)transition | 862 transition:(ui::PageTransition)transition |
862 useDesktopUserAgent:(BOOL)useDesktopUserAgent | 863 useDesktopUserAgent:(BOOL)useDesktopUserAgent |
863 rendererInitiated:(BOOL)rendererInitiated { | 864 rendererInitiated:(BOOL)rendererInitiated { |
864 GURL loaded_url(url); | 865 GURL loaded_url(url); |
865 web::BrowserURLRewriter::GetInstance()->RewriteURLIfNecessary(&loaded_url, | 866 web::BrowserURLRewriter::GetInstance()->RewriteURLIfNecessary(&loaded_url, |
866 _browserState); | 867 _browserState); |
867 return [[[CRWSessionEntry alloc] initWithUrl:loaded_url | 868 scoped_ptr<web::NavigationItemImpl> item(new web::NavigationItemImpl()); |
868 referrer:referrer | 869 item->SetURL(loaded_url); |
869 transition:transition | 870 item->SetReferrer(referrer); |
870 useDesktopUserAgent:useDesktopUserAgent | 871 item->SetTransitionType(transition); |
871 rendererInitiated:rendererInitiated] autorelease]; | 872 item->SetIsOverridingUserAgent(useDesktopUserAgent); |
| 873 item->set_is_renderer_initiated(rendererInitiated); |
| 874 return [[CRWSessionEntry alloc] initWithNavigationItem:item.Pass()]; |
872 } | 875 } |
873 | 876 |
874 @end | 877 @end |
OLD | NEW |