OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 #include "chrome/browser/tab_contents/navigation_controller.h" | 5 #include "chrome/browser/tab_contents/navigation_controller.h" |
6 | 6 |
7 #include "app/resource_bundle.h" | 7 #include "app/resource_bundle.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 new_entry = new NavigationEntry; | 598 new_entry = new NavigationEntry; |
599 } | 599 } |
600 | 600 |
601 new_entry->set_url(params.url); | 601 new_entry->set_url(params.url); |
602 new_entry->set_referrer(params.referrer); | 602 new_entry->set_referrer(params.referrer); |
603 new_entry->set_page_id(params.page_id); | 603 new_entry->set_page_id(params.page_id); |
604 new_entry->set_transition_type(params.transition); | 604 new_entry->set_transition_type(params.transition); |
605 new_entry->set_site_instance(tab_contents_->GetSiteInstance()); | 605 new_entry->set_site_instance(tab_contents_->GetSiteInstance()); |
606 new_entry->set_has_post_data(params.is_post); | 606 new_entry->set_has_post_data(params.is_post); |
607 | 607 |
608 InsertEntry(new_entry); | 608 // If the current entry is a redirection source, it needs to be replaced with |
| 609 // the new entry to avoid unwanted redirections in navigating backward / |
| 610 // forward. Otherwise, just insert the new entry. |
| 611 InsertOrReplaceEntry(new_entry, |
| 612 PageTransition::IsRedirect(new_entry->transition_type())); |
609 } | 613 } |
610 | 614 |
611 void NavigationController::RendererDidNavigateToExistingPage( | 615 void NavigationController::RendererDidNavigateToExistingPage( |
612 const ViewHostMsg_FrameNavigate_Params& params) { | 616 const ViewHostMsg_FrameNavigate_Params& params) { |
613 // We should only get here for main frame navigations. | 617 // We should only get here for main frame navigations. |
614 DCHECK(PageTransition::IsMainFrame(params.transition)); | 618 DCHECK(PageTransition::IsMainFrame(params.transition)); |
615 | 619 |
616 // This is a back/forward navigation. The existing page for the ID is | 620 // This is a back/forward navigation. The existing page for the ID is |
617 // guaranteed to exist by ClassifyNavigation, and we just need to update it | 621 // guaranteed to exist by ClassifyNavigation, and we just need to update it |
618 // with new information from the renderer. | 622 // with new information from the renderer. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 NavigationEntry* existing_entry = GetEntryWithPageID( | 671 NavigationEntry* existing_entry = GetEntryWithPageID( |
668 tab_contents_->GetSiteInstance(), | 672 tab_contents_->GetSiteInstance(), |
669 params.page_id); | 673 params.page_id); |
670 | 674 |
671 // Reference fragment navigation. We're guaranteed to have the last_committed | 675 // Reference fragment navigation. We're guaranteed to have the last_committed |
672 // entry and it will be the same page as the new navigation (minus the | 676 // entry and it will be the same page as the new navigation (minus the |
673 // reference fragments, of course). | 677 // reference fragments, of course). |
674 NavigationEntry* new_entry = new NavigationEntry(*existing_entry); | 678 NavigationEntry* new_entry = new NavigationEntry(*existing_entry); |
675 new_entry->set_page_id(params.page_id); | 679 new_entry->set_page_id(params.page_id); |
676 new_entry->set_url(params.url); | 680 new_entry->set_url(params.url); |
677 InsertEntry(new_entry); | 681 InsertOrReplaceEntry(new_entry, false); |
678 } | 682 } |
679 | 683 |
680 void NavigationController::RendererDidNavigateNewSubframe( | 684 void NavigationController::RendererDidNavigateNewSubframe( |
681 const ViewHostMsg_FrameNavigate_Params& params) { | 685 const ViewHostMsg_FrameNavigate_Params& params) { |
682 // Manual subframe navigations just get the current entry cloned so the user | 686 // Manual subframe navigations just get the current entry cloned so the user |
683 // can go back or forward to it. The actual subframe information will be | 687 // can go back or forward to it. The actual subframe information will be |
684 // stored in the page state for each of those entries. This happens out of | 688 // stored in the page state for each of those entries. This happens out of |
685 // band with the actual navigations. | 689 // band with the actual navigations. |
686 DCHECK(GetLastCommittedEntry()) << "ClassifyNavigation should guarantee " | 690 DCHECK(GetLastCommittedEntry()) << "ClassifyNavigation should guarantee " |
687 << "that a last committed entry exists."; | 691 << "that a last committed entry exists."; |
688 NavigationEntry* new_entry = new NavigationEntry(*GetLastCommittedEntry()); | 692 NavigationEntry* new_entry = new NavigationEntry(*GetLastCommittedEntry()); |
689 new_entry->set_page_id(params.page_id); | 693 new_entry->set_page_id(params.page_id); |
690 InsertEntry(new_entry); | 694 InsertOrReplaceEntry(new_entry, false); |
691 } | 695 } |
692 | 696 |
693 bool NavigationController::RendererDidNavigateAutoSubframe( | 697 bool NavigationController::RendererDidNavigateAutoSubframe( |
694 const ViewHostMsg_FrameNavigate_Params& params) { | 698 const ViewHostMsg_FrameNavigate_Params& params) { |
695 // We're guaranteed to have a previously committed entry, and we now need to | 699 // We're guaranteed to have a previously committed entry, and we now need to |
696 // handle navigation inside of a subframe in it without creating a new entry. | 700 // handle navigation inside of a subframe in it without creating a new entry. |
697 DCHECK(GetLastCommittedEntry()); | 701 DCHECK(GetLastCommittedEntry()); |
698 | 702 |
699 // Handle the case where we're navigating back/forward to a previous subframe | 703 // Handle the case where we're navigating back/forward to a previous subframe |
700 // navigation entry. This is case "2." in NAV_AUTO_SUBFRAME comment in the | 704 // navigation entry. This is case "2." in NAV_AUTO_SUBFRAME comment in the |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 // This is a previous navigation (back/forward) that we're just now | 740 // This is a previous navigation (back/forward) that we're just now |
737 // committing. Just mark it as committed. | 741 // committing. Just mark it as committed. |
738 details.type = NavigationType::EXISTING_PAGE; | 742 details.type = NavigationType::EXISTING_PAGE; |
739 int new_entry_index = pending_entry_index_; | 743 int new_entry_index = pending_entry_index_; |
740 DiscardNonCommittedEntriesInternal(); | 744 DiscardNonCommittedEntriesInternal(); |
741 | 745 |
742 // Mark that entry as committed. | 746 // Mark that entry as committed. |
743 last_committed_entry_index_ = new_entry_index; | 747 last_committed_entry_index_ = new_entry_index; |
744 } else { | 748 } else { |
745 // This is a new navigation. It's easiest to just copy the entry and insert | 749 // This is a new navigation. It's easiest to just copy the entry and insert |
746 // it new again, since InsertEntry expects to take ownership and also | 750 // it new again, since InsertOrReplaceEntry expects to take ownership and |
747 // discard the pending entry. We also need to synthesize a page ID. We can | 751 // also discard the pending entry. We also need to synthesize a page ID. We |
748 // only do this because this function will only be called by our custom | 752 // can only do this because this function will only be called by our custom |
749 // TabContents types. For TabContents, the IDs are generated by the | 753 // TabContents types. For TabContents, the IDs are generated by the |
750 // renderer, so we can't do this. | 754 // renderer, so we can't do this. |
751 details.type = NavigationType::NEW_PAGE; | 755 details.type = NavigationType::NEW_PAGE; |
752 pending_entry_->set_page_id(tab_contents_->GetMaxPageID() + 1); | 756 pending_entry_->set_page_id(tab_contents_->GetMaxPageID() + 1); |
753 tab_contents_->UpdateMaxPageID(pending_entry_->page_id()); | 757 tab_contents_->UpdateMaxPageID(pending_entry_->page_id()); |
754 InsertEntry(new NavigationEntry(*pending_entry_)); | 758 InsertOrReplaceEntry(new NavigationEntry(*pending_entry_), false); |
755 } | 759 } |
756 | 760 |
757 // Broadcast the notification of the navigation. | 761 // Broadcast the notification of the navigation. |
758 details.entry = GetActiveEntry(); | 762 details.entry = GetActiveEntry(); |
759 details.is_auto = false; | 763 details.is_auto = false; |
760 details.is_in_page = AreURLsInPageNavigation(details.previous_url, | 764 details.is_in_page = AreURLsInPageNavigation(details.previous_url, |
761 details.entry->url()); | 765 details.entry->url()); |
762 details.is_main_frame = true; | 766 details.is_main_frame = true; |
763 NotifyNavigationEntryCommitted(&details); | 767 NotifyNavigationEntryCommitted(&details); |
764 } | 768 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
800 DiscardNonCommittedEntriesInternal(); | 804 DiscardNonCommittedEntriesInternal(); |
801 | 805 |
802 // If there was a transient entry, invalidate everything so the new active | 806 // If there was a transient entry, invalidate everything so the new active |
803 // entry state is shown. | 807 // entry state is shown. |
804 if (transient) { | 808 if (transient) { |
805 tab_contents_->NotifyNavigationStateChanged( | 809 tab_contents_->NotifyNavigationStateChanged( |
806 TabContents::INVALIDATE_EVERYTHING); | 810 TabContents::INVALIDATE_EVERYTHING); |
807 } | 811 } |
808 } | 812 } |
809 | 813 |
810 void NavigationController::InsertEntry(NavigationEntry* entry) { | 814 void NavigationController::InsertOrReplaceEntry(NavigationEntry* entry, |
| 815 bool replace) { |
811 DCHECK(entry->transition_type() != PageTransition::AUTO_SUBFRAME); | 816 DCHECK(entry->transition_type() != PageTransition::AUTO_SUBFRAME); |
812 | 817 |
813 // Copy the pending entry's unique ID to the committed entry. | 818 // Copy the pending entry's unique ID to the committed entry. |
814 // I don't know if pending_entry_index_ can be other than -1 here. | 819 // I don't know if pending_entry_index_ can be other than -1 here. |
815 const NavigationEntry* const pending_entry = (pending_entry_index_ == -1) ? | 820 const NavigationEntry* const pending_entry = (pending_entry_index_ == -1) ? |
816 pending_entry_ : entries_[pending_entry_index_].get(); | 821 pending_entry_ : entries_[pending_entry_index_].get(); |
817 if (pending_entry) | 822 if (pending_entry) |
818 entry->set_unique_id(pending_entry->unique_id()); | 823 entry->set_unique_id(pending_entry->unique_id()); |
819 | 824 |
820 DiscardNonCommittedEntriesInternal(); | 825 DiscardNonCommittedEntriesInternal(); |
821 | 826 |
822 int current_size = static_cast<int>(entries_.size()); | 827 int current_size = static_cast<int>(entries_.size()); |
823 | 828 |
824 // Prune any entries which are in front of the current entry. | |
825 if (current_size > 0) { | 829 if (current_size > 0) { |
| 830 // Prune any entries which are in front of the current entry. |
| 831 // Also prune the current entry if we are to replace the current entry. |
| 832 int prune_up_to = replace ? last_committed_entry_index_ - 1 |
| 833 : last_committed_entry_index_; |
826 int num_pruned = 0; | 834 int num_pruned = 0; |
827 while (last_committed_entry_index_ < (current_size - 1)) { | 835 while (prune_up_to < (current_size - 1)) { |
828 num_pruned++; | 836 num_pruned++; |
829 entries_.pop_back(); | 837 entries_.pop_back(); |
830 current_size--; | 838 current_size--; |
831 } | 839 } |
832 if (num_pruned > 0) // Only notify if we did prune something. | 840 if (num_pruned > 0) // Only notify if we did prune something. |
833 NotifyPrunedEntries(this, false, num_pruned); | 841 NotifyPrunedEntries(this, false, num_pruned); |
834 } | 842 } |
835 | 843 |
836 if (entries_.size() >= max_entry_count_) { | 844 if (entries_.size() >= max_entry_count_) { |
837 RemoveEntryAtIndex(0, GURL()); | 845 RemoveEntryAtIndex(0, GURL()); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
957 return i; | 965 return i; |
958 } | 966 } |
959 return -1; | 967 return -1; |
960 } | 968 } |
961 | 969 |
962 NavigationEntry* NavigationController::GetTransientEntry() const { | 970 NavigationEntry* NavigationController::GetTransientEntry() const { |
963 if (transient_entry_index_ == -1) | 971 if (transient_entry_index_ == -1) |
964 return NULL; | 972 return NULL; |
965 return entries_[transient_entry_index_].get(); | 973 return entries_[transient_entry_index_].get(); |
966 } | 974 } |
OLD | NEW |