| 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 |