| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 @property(nonatomic, readwrite, assign) NSInteger previousNavigationIndex; | 104 @property(nonatomic, readwrite, assign) NSInteger previousNavigationIndex; |
| 105 | 105 |
| 106 // Removes all entries after currentNavigationIndex_. | 106 // Removes all entries after currentNavigationIndex_. |
| 107 - (void)clearForwardItems; | 107 - (void)clearForwardItems; |
| 108 // Discards the transient entry, if any. | 108 // Discards the transient entry, if any. |
| 109 - (void)discardTransientItem; | 109 - (void)discardTransientItem; |
| 110 // Create a new autoreleased session entry. | 110 // Create a new autoreleased session entry. |
| 111 - (CRWSessionEntry*)sessionEntryWithURL:(const GURL&)url | 111 - (CRWSessionEntry*)sessionEntryWithURL:(const GURL&)url |
| 112 referrer:(const web::Referrer&)referrer | 112 referrer:(const web::Referrer&)referrer |
| 113 transition:(ui::PageTransition)transition | 113 transition:(ui::PageTransition)transition |
| 114 useDesktopUserAgent:(BOOL)useDesktopUserAgent | 114 initiationType: |
| 115 rendererInitiated:(BOOL)rendererInitiated; | 115 (web::NavigationInitiationType)initiationType; |
| 116 // Returns YES if the PageTransition for the underlying navigationItem at | 116 // Returns YES if the PageTransition for the underlying navigationItem at |
| 117 // |index| in |entries_| has ui::PAGE_TRANSITION_IS_REDIRECT_MASK. | 117 // |index| in |entries_| has ui::PAGE_TRANSITION_IS_REDIRECT_MASK. |
| 118 - (BOOL)isRedirectTransitionForItemAtIndex:(NSInteger)index; | 118 - (BOOL)isRedirectTransitionForItemAtIndex:(NSInteger)index; |
| 119 // Returns a NavigationItemList containing the NavigationItems from |entries|. | 119 // Returns a NavigationItemList containing the NavigationItems from |entries|. |
| 120 - (web::NavigationItemList)itemListForEntryList:(NSArray*)entries; | 120 - (web::NavigationItemList)itemListForEntryList:(NSArray*)entries; |
| 121 @end | 121 @end |
| 122 | 122 |
| 123 @implementation CRWSessionController | 123 @implementation CRWSessionController |
| 124 | 124 |
| 125 @synthesize currentNavigationIndex = _currentNavigationIndex; | 125 @synthesize currentNavigationIndex = _currentNavigationIndex; |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 } | 305 } |
| 306 | 306 |
| 307 // See NavigationController::GetVisibleEntry for the motivation for this | 307 // See NavigationController::GetVisibleEntry for the motivation for this |
| 308 // distinction. | 308 // distinction. |
| 309 - (CRWSessionEntry*)visibleEntry { | 309 - (CRWSessionEntry*)visibleEntry { |
| 310 if (_transientEntry) | 310 if (_transientEntry) |
| 311 return _transientEntry.get(); | 311 return _transientEntry.get(); |
| 312 // Only return the pending_entry for new (non-history), browser-initiated | 312 // Only return the pending_entry for new (non-history), browser-initiated |
| 313 // navigations in order to prevent URL spoof attacks. | 313 // navigations in order to prevent URL spoof attacks. |
| 314 web::NavigationItemImpl* pendingItem = [_pendingEntry navigationItemImpl]; | 314 web::NavigationItemImpl* pendingItem = [_pendingEntry navigationItemImpl]; |
| 315 bool safeToShowPending = pendingItem && | 315 |
| 316 !pendingItem->is_renderer_initiated() && | 316 if (pendingItem) { |
| 317 _pendingItemIndex == -1; | 317 bool isUserInitiated = pendingItem->NavigationInitiationType() == |
| 318 if (safeToShowPending) { | 318 web::NavigationInitiationType::USER_INITIATED; |
| 319 return _pendingEntry.get(); | 319 bool safeToShowPending = isUserInitiated && _pendingItemIndex == -1; |
| 320 |
| 321 if (safeToShowPending) |
| 322 return _pendingEntry.get(); |
| 320 } | 323 } |
| 324 |
| 321 return [self lastCommittedEntry]; | 325 return [self lastCommittedEntry]; |
| 322 } | 326 } |
| 323 | 327 |
| 324 - (CRWSessionEntry*)pendingEntry { | 328 - (CRWSessionEntry*)pendingEntry { |
| 325 return _pendingEntry.get(); | 329 return _pendingEntry.get(); |
| 326 } | 330 } |
| 327 | 331 |
| 328 - (CRWSessionEntry*)transientEntry { | 332 - (CRWSessionEntry*)transientEntry { |
| 329 return _transientEntry.get(); | 333 return _transientEntry.get(); |
| 330 } | 334 } |
| 331 | 335 |
| 332 - (CRWSessionEntry*)lastCommittedEntry { | 336 - (CRWSessionEntry*)lastCommittedEntry { |
| 333 if (_currentNavigationIndex == -1) | 337 if (_currentNavigationIndex == -1) |
| 334 return nil; | 338 return nil; |
| 335 return [_entries objectAtIndex:_currentNavigationIndex]; | 339 return [_entries objectAtIndex:_currentNavigationIndex]; |
| 336 } | 340 } |
| 337 | 341 |
| 338 // Returns the previous entry in the session list, or nil if there isn't any. | 342 // Returns the previous entry in the session list, or nil if there isn't any. |
| 339 - (CRWSessionEntry*)previousEntry { | 343 - (CRWSessionEntry*)previousEntry { |
| 340 if ((_previousNavigationIndex < 0) || (![_entries count])) | 344 if ((_previousNavigationIndex < 0) || (![_entries count])) |
| 341 return nil; | 345 return nil; |
| 342 return [_entries objectAtIndex:_previousNavigationIndex]; | 346 return [_entries objectAtIndex:_previousNavigationIndex]; |
| 343 } | 347 } |
| 344 | 348 |
| 345 - (void)addPendingItem:(const GURL&)url | 349 - (void)addPendingItem:(const GURL&)url |
| 346 referrer:(const web::Referrer&)ref | 350 referrer:(const web::Referrer&)ref |
| 347 transition:(ui::PageTransition)trans | 351 transition:(ui::PageTransition)trans |
| 348 rendererInitiated:(BOOL)rendererInitiated { | 352 initiationType:(web::NavigationInitiationType)initiationType { |
| 349 [self discardTransientItem]; | 353 [self discardTransientItem]; |
| 350 _pendingItemIndex = -1; | 354 _pendingItemIndex = -1; |
| 351 | 355 |
| 352 // Don't create a new entry if it's already the same as the current entry, | 356 // Don't create a new entry if it's already the same as the current entry, |
| 353 // allowing this routine to be called multiple times in a row without issue. | 357 // allowing this routine to be called multiple times in a row without issue. |
| 354 // Note: CRWSessionController currently has the responsibility to distinguish | 358 // Note: CRWSessionController currently has the responsibility to distinguish |
| 355 // between new navigations and history stack navigation, hence the inclusion | 359 // between new navigations and history stack navigation, hence the inclusion |
| 356 // of specific transiton type logic here, in order to make it reliable with | 360 // of specific transiton type logic here, in order to make it reliable with |
| 357 // real-world observed behavior. | 361 // real-world observed behavior. |
| 358 // TODO(crbug.com/676129): Fix the way changes are detected/reported elsewhere | 362 // TODO(crbug.com/676129): Fix the way changes are detected/reported elsewhere |
| 359 // in the web layer so that this hack can be removed. | 363 // in the web layer so that this hack can be removed. |
| 360 // Remove the workaround code from -presentSafeBrowsingWarningForResource:. | 364 // Remove the workaround code from -presentSafeBrowsingWarningForResource:. |
| 361 CRWSessionEntry* currentEntry = self.currentEntry; | 365 CRWSessionEntry* currentEntry = self.currentEntry; |
| 362 if (currentEntry) { | 366 if (currentEntry) { |
| 363 web::NavigationItem* item = [currentEntry navigationItem]; | 367 web::NavigationItem* item = [currentEntry navigationItem]; |
| 364 if (item->GetURL() == url && | 368 |
| 365 (!PageTransitionCoreTypeIs(trans, ui::PAGE_TRANSITION_FORM_SUBMIT) || | 369 BOOL hasSameURL = item->GetURL() == url; |
| 366 PageTransitionCoreTypeIs(item->GetTransitionType(), | 370 BOOL isPendingTransitionFormSubmit = |
| 367 ui::PAGE_TRANSITION_FORM_SUBMIT))) { | 371 PageTransitionCoreTypeIs(trans, ui::PAGE_TRANSITION_FORM_SUBMIT); |
| 372 BOOL isCurrentTransitionFormSubmit = PageTransitionCoreTypeIs( |
| 373 item->GetTransitionType(), ui::PAGE_TRANSITION_FORM_SUBMIT); |
| 374 BOOL shouldCreatePendingItem = |
| 375 !hasSameURL || |
| 376 (isPendingTransitionFormSubmit && !isCurrentTransitionFormSubmit); |
| 377 |
| 378 if (!shouldCreatePendingItem) { |
| 368 // Send the notification anyway, to preserve old behavior. It's unknown | 379 // Send the notification anyway, to preserve old behavior. It's unknown |
| 369 // whether anything currently relies on this, but since both this whole | 380 // whether anything currently relies on this, but since both this whole |
| 370 // hack and the content facade will both be going away, it's not worth | 381 // hack and the content facade will both be going away, it's not worth |
| 371 // trying to unwind. | 382 // trying to unwind. |
| 372 if (_navigationManager && _navigationManager->GetFacadeDelegate()) { | 383 if (_navigationManager && _navigationManager->GetFacadeDelegate()) { |
| 373 _navigationManager->GetFacadeDelegate()->OnNavigationItemPending(); | 384 _navigationManager->GetFacadeDelegate()->OnNavigationItemPending(); |
| 374 } | 385 } |
| 375 return; | 386 return; |
| 376 } | 387 } |
| 377 } | 388 } |
| 378 | 389 |
| 379 BOOL useDesktopUserAgent = | |
| 380 _useDesktopUserAgentForNextPendingItem || | |
| 381 (self.currentEntry.navigationItem && | |
| 382 self.currentEntry.navigationItem->IsOverridingUserAgent()); | |
| 383 _useDesktopUserAgentForNextPendingItem = NO; | |
| 384 _pendingEntry.reset([self sessionEntryWithURL:url | 390 _pendingEntry.reset([self sessionEntryWithURL:url |
| 385 referrer:ref | 391 referrer:ref |
| 386 transition:trans | 392 transition:trans |
| 387 useDesktopUserAgent:useDesktopUserAgent | 393 initiationType:initiationType]); |
| 388 rendererInitiated:rendererInitiated]); | |
| 389 | 394 |
| 390 if (_navigationManager && _navigationManager->GetFacadeDelegate()) { | 395 if (_navigationManager && _navigationManager->GetFacadeDelegate()) { |
| 391 _navigationManager->GetFacadeDelegate()->OnNavigationItemPending(); | 396 _navigationManager->GetFacadeDelegate()->OnNavigationItemPending(); |
| 392 } | 397 } |
| 393 } | 398 } |
| 394 | 399 |
| 395 - (void)updatePendingItem:(const GURL&)url { | 400 - (void)updatePendingItem:(const GURL&)url { |
| 396 // If there is no pending entry, navigation is probably happening within the | 401 // If there is no pending entry, navigation is probably happening within the |
| 397 // session history. Don't modify the entry list. | 402 // session history. Don't modify the entry list. |
| 398 if (!_pendingEntry) | 403 if (!_pendingEntry) |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 if (_navigationManager && item) | 476 if (_navigationManager && item) |
| 472 _navigationManager->OnNavigationItemCommitted(); | 477 _navigationManager->OnNavigationItemCommitted(); |
| 473 DCHECK_EQ(_pendingItemIndex, -1); | 478 DCHECK_EQ(_pendingItemIndex, -1); |
| 474 } | 479 } |
| 475 | 480 |
| 476 - (void)addTransientItemWithURL:(const GURL&)URL { | 481 - (void)addTransientItemWithURL:(const GURL&)URL { |
| 477 _transientEntry.reset([self | 482 _transientEntry.reset([self |
| 478 sessionEntryWithURL:URL | 483 sessionEntryWithURL:URL |
| 479 referrer:web::Referrer() | 484 referrer:web::Referrer() |
| 480 transition:ui::PAGE_TRANSITION_CLIENT_REDIRECT | 485 transition:ui::PAGE_TRANSITION_CLIENT_REDIRECT |
| 481 useDesktopUserAgent:NO | 486 initiationType:web::NavigationInitiationType::USER_INITIATED]); |
| 482 rendererInitiated:NO]); | |
| 483 | 487 |
| 484 web::NavigationItem* navigationItem = [_transientEntry navigationItem]; | 488 web::NavigationItem* navigationItem = [_transientEntry navigationItem]; |
| 485 DCHECK(navigationItem); | 489 DCHECK(navigationItem); |
| 486 navigationItem->SetTimestamp( | 490 navigationItem->SetTimestamp( |
| 487 _timeSmoother.GetSmoothedTime(base::Time::Now())); | 491 _timeSmoother.GetSmoothedTime(base::Time::Now())); |
| 488 } | 492 } |
| 489 | 493 |
| 490 - (void)pushNewItemWithURL:(const GURL&)URL | 494 - (void)pushNewItemWithURL:(const GURL&)URL |
| 491 stateObject:(NSString*)stateObject | 495 stateObject:(NSString*)stateObject |
| 492 transition:(ui::PageTransition)transition { | 496 transition:(ui::PageTransition)transition { |
| 493 DCHECK(![self pendingEntry]); | 497 DCHECK(![self pendingEntry]); |
| 494 DCHECK([self currentEntry]); | 498 DCHECK([self currentEntry]); |
| 495 web::NavigationItem* item = [self currentEntry].navigationItem; | 499 web::NavigationItem* currentItem = [self currentEntry].navigationItem; |
| 496 CHECK( | 500 CHECK(web::history_state_util::IsHistoryStateChangeValid( |
| 497 web::history_state_util::IsHistoryStateChangeValid(item->GetURL(), URL)); | 501 currentItem->GetURL(), URL)); |
| 498 web::Referrer referrer(item->GetURL(), web::ReferrerPolicyDefault); | 502 web::Referrer referrer(currentItem->GetURL(), web::ReferrerPolicyDefault); |
| 499 bool overrideUserAgent = | 503 |
| 500 self.currentEntry.navigationItem->IsOverridingUserAgent(); | |
| 501 base::scoped_nsobject<CRWSessionEntry> pushedEntry([self | 504 base::scoped_nsobject<CRWSessionEntry> pushedEntry([self |
| 502 sessionEntryWithURL:URL | 505 sessionEntryWithURL:URL |
| 503 referrer:referrer | 506 referrer:referrer |
| 504 transition:transition | 507 transition:transition |
| 505 useDesktopUserAgent:overrideUserAgent | 508 initiationType:web::NavigationInitiationType::USER_INITIATED]); |
| 506 rendererInitiated:NO]); | 509 |
| 507 web::NavigationItemImpl* pushedItem = [pushedEntry navigationItemImpl]; | 510 web::NavigationItemImpl* pushedItem = [pushedEntry navigationItemImpl]; |
| 511 pushedItem->SetIsOverridingUserAgent(currentItem->IsOverridingUserAgent()); |
| 508 pushedItem->SetSerializedStateObject(stateObject); | 512 pushedItem->SetSerializedStateObject(stateObject); |
| 509 pushedItem->SetIsCreatedFromPushState(true); | 513 pushedItem->SetIsCreatedFromPushState(true); |
| 510 web::SSLStatus& sslStatus = [self currentEntry].navigationItem->GetSSL(); | 514 web::SSLStatus& sslStatus = [self currentEntry].navigationItem->GetSSL(); |
| 511 pushedEntry.get().navigationItem->GetSSL() = sslStatus; | 515 pushedEntry.get().navigationItem->GetSSL() = sslStatus; |
| 512 | 516 |
| 513 [self clearForwardItems]; | 517 [self clearForwardItems]; |
| 514 // Add the new entry at the end. | 518 // Add the new entry at the end. |
| 515 [_entries addObject:pushedEntry]; | 519 [_entries addObject:pushedEntry]; |
| 516 _previousNavigationIndex = _currentNavigationIndex; | 520 _previousNavigationIndex = _currentNavigationIndex; |
| 517 self.currentNavigationIndex = [_entries count] - 1; | 521 self.currentNavigationIndex = [_entries count] - 1; |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 | 670 |
| 667 NSInteger index = _currentNavigationIndex; | 671 NSInteger index = _currentNavigationIndex; |
| 668 // This will return the first session entry if all other entries are | 672 // This will return the first session entry if all other entries are |
| 669 // redirects, regardless of the transition state of the first entry. | 673 // redirects, regardless of the transition state of the first entry. |
| 670 while (index > 0 && [self isRedirectTransitionForItemAtIndex:index]) { | 674 while (index > 0 && [self isRedirectTransitionForItemAtIndex:index]) { |
| 671 --index; | 675 --index; |
| 672 } | 676 } |
| 673 return [_entries objectAtIndex:index]; | 677 return [_entries objectAtIndex:index]; |
| 674 } | 678 } |
| 675 | 679 |
| 676 - (void)useDesktopUserAgentForNextPendingItem { | |
| 677 if (_pendingEntry) | |
| 678 [_pendingEntry navigationItem]->SetIsOverridingUserAgent(true); | |
| 679 else | |
| 680 _useDesktopUserAgentForNextPendingItem = YES; | |
| 681 } | |
| 682 | |
| 683 - (NSInteger)indexOfItem:(const web::NavigationItem*)item { | 680 - (NSInteger)indexOfItem:(const web::NavigationItem*)item { |
| 684 web::NavigationItemList items = self.items; | 681 web::NavigationItemList items = self.items; |
| 685 for (NSInteger i = 0; i < static_cast<NSInteger>(items.size()); ++i) { | 682 for (NSInteger i = 0; i < static_cast<NSInteger>(items.size()); ++i) { |
| 686 if (items[i] == item) | 683 if (items[i] == item) |
| 687 return i; | 684 return i; |
| 688 } | 685 } |
| 689 return NSNotFound; | 686 return NSNotFound; |
| 690 } | 687 } |
| 691 | 688 |
| 692 #pragma mark - | 689 #pragma mark - |
| 693 #pragma mark Private methods | 690 #pragma mark Private methods |
| 694 | 691 |
| 695 - (CRWSessionEntry*)sessionEntryWithURL:(const GURL&)url | 692 - (CRWSessionEntry*)sessionEntryWithURL:(const GURL&)url |
| 696 referrer:(const web::Referrer&)referrer | 693 referrer:(const web::Referrer&)referrer |
| 697 transition:(ui::PageTransition)transition | 694 transition:(ui::PageTransition)transition |
| 698 useDesktopUserAgent:(BOOL)useDesktopUserAgent | 695 initiationType: |
| 699 rendererInitiated:(BOOL)rendererInitiated { | 696 (web::NavigationInitiationType)initiationType { |
| 700 GURL loaded_url(url); | 697 GURL loaded_url(url); |
| 701 BOOL urlWasRewritten = NO; | 698 BOOL urlWasRewritten = NO; |
| 702 if (_navigationManager) { | 699 if (_navigationManager) { |
| 703 std::unique_ptr<std::vector<web::BrowserURLRewriter::URLRewriter>> | 700 std::unique_ptr<std::vector<web::BrowserURLRewriter::URLRewriter>> |
| 704 transientRewriters = _navigationManager->GetTransientURLRewriters(); | 701 transientRewriters = _navigationManager->GetTransientURLRewriters(); |
| 705 if (transientRewriters) { | 702 if (transientRewriters) { |
| 706 urlWasRewritten = web::BrowserURLRewriter::RewriteURLWithWriters( | 703 urlWasRewritten = web::BrowserURLRewriter::RewriteURLWithWriters( |
| 707 &loaded_url, _browserState, *transientRewriters.get()); | 704 &loaded_url, _browserState, *transientRewriters.get()); |
| 708 } | 705 } |
| 709 } | 706 } |
| 710 if (!urlWasRewritten) { | 707 if (!urlWasRewritten) { |
| 711 web::BrowserURLRewriter::GetInstance()->RewriteURLIfNecessary( | 708 web::BrowserURLRewriter::GetInstance()->RewriteURLIfNecessary( |
| 712 &loaded_url, _browserState); | 709 &loaded_url, _browserState); |
| 713 } | 710 } |
| 711 |
| 714 std::unique_ptr<web::NavigationItemImpl> item(new web::NavigationItemImpl()); | 712 std::unique_ptr<web::NavigationItemImpl> item(new web::NavigationItemImpl()); |
| 715 item->SetOriginalRequestURL(loaded_url); | 713 item->SetOriginalRequestURL(loaded_url); |
| 716 item->SetURL(loaded_url); | 714 item->SetURL(loaded_url); |
| 717 item->SetReferrer(referrer); | 715 item->SetReferrer(referrer); |
| 718 item->SetTransitionType(transition); | 716 item->SetTransitionType(transition); |
| 719 item->SetIsOverridingUserAgent(useDesktopUserAgent); | 717 item->SetNavigationInitiationType(initiationType); |
| 720 item->set_is_renderer_initiated(rendererInitiated); | |
| 721 return [[CRWSessionEntry alloc] initWithNavigationItem:std::move(item)]; | 718 return [[CRWSessionEntry alloc] initWithNavigationItem:std::move(item)]; |
| 722 } | 719 } |
| 723 | 720 |
| 724 - (BOOL)isRedirectTransitionForItemAtIndex:(NSInteger)index { | 721 - (BOOL)isRedirectTransitionForItemAtIndex:(NSInteger)index { |
| 725 ui::PageTransition transition = | 722 ui::PageTransition transition = |
| 726 [_entries[index] navigationItem]->GetTransitionType(); | 723 [_entries[index] navigationItem]->GetTransitionType(); |
| 727 return (transition & ui::PAGE_TRANSITION_IS_REDIRECT_MASK) ? YES : NO; | 724 return (transition & ui::PAGE_TRANSITION_IS_REDIRECT_MASK) ? YES : NO; |
| 728 } | 725 } |
| 729 | 726 |
| 730 - (web::NavigationItemList)itemListForEntryList:(NSArray*)entries { | 727 - (web::NavigationItemList)itemListForEntryList:(NSArray*)entries { |
| 731 web::NavigationItemList list(entries.count); | 728 web::NavigationItemList list(entries.count); |
| 732 for (size_t index = 0; index < entries.count; ++index) | 729 for (size_t index = 0; index < entries.count; ++index) |
| 733 list[index] = [entries[index] navigationItem]; | 730 list[index] = [entries[index] navigationItem]; |
| 734 return list; | 731 return list; |
| 735 } | 732 } |
| 736 | 733 |
| 737 @end | 734 @end |
| OLD | NEW |