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

Side by Side Diff: content/browser/frame_host/navigation_controller_impl.cc

Issue 281653003: DRAFT CL: Add FrameNavigationEntry and track subframe session histories. Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 5 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "content/browser/frame_host/navigation_controller_impl.h" 5 #include "content/browser/frame_host/navigation_controller_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "base/strings/string_number_conversions.h" // Temporary 11 #include "base/strings/string_number_conversions.h" // Temporary
12 #include "base/strings/string_util.h" 12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
14 #include "base/time/time.h" 14 #include "base/time/time.h"
15 #include "base/trace_event/trace_event.h" 15 #include "base/trace_event/trace_event.h"
16 #include "cc/base/switches.h" 16 #include "cc/base/switches.h"
17 #include "content/browser/browser_url_handler_impl.h" 17 #include "content/browser/browser_url_handler_impl.h"
18 #include "content/browser/dom_storage/dom_storage_context_wrapper.h" 18 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
19 #include "content/browser/dom_storage/session_storage_namespace_impl.h" 19 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
20 #include "content/browser/frame_host/debug_urls.h" 20 #include "content/browser/frame_host/debug_urls.h"
21 #include "content/browser/frame_host/frame_navigation_entry.h"
21 #include "content/browser/frame_host/interstitial_page_impl.h" 22 #include "content/browser/frame_host/interstitial_page_impl.h"
22 #include "content/browser/frame_host/navigation_entry_impl.h" 23 #include "content/browser/frame_host/navigation_entry_impl.h"
23 #include "content/browser/frame_host/navigation_entry_screenshot_manager.h" 24 #include "content/browser/frame_host/navigation_entry_screenshot_manager.h"
25 #include "content/browser/frame_host/navigator_impl.h"
24 #include "content/browser/renderer_host/render_view_host_impl.h" // Temporary 26 #include "content/browser/renderer_host/render_view_host_impl.h" // Temporary
25 #include "content/browser/site_instance_impl.h" 27 #include "content/browser/site_instance_impl.h"
26 #include "content/common/frame_messages.h" 28 #include "content/common/frame_messages.h"
27 #include "content/common/view_messages.h" 29 #include "content/common/view_messages.h"
28 #include "content/public/browser/browser_context.h" 30 #include "content/public/browser/browser_context.h"
29 #include "content/public/browser/content_browser_client.h" 31 #include "content/public/browser/content_browser_client.h"
30 #include "content/public/browser/invalidate_type.h" 32 #include "content/public/browser/invalidate_type.h"
31 #include "content/public/browser/navigation_details.h" 33 #include "content/public/browser/navigation_details.h"
32 #include "content/public/browser/notification_service.h" 34 #include "content/public/browser/notification_service.h"
33 #include "content/public/browser/notification_types.h" 35 #include "content/public/browser/notification_types.h"
(...skipping 29 matching lines...) Expand all
63 } 65 }
64 66
65 // Ensure the given NavigationEntry has a valid state, so that WebKit does not 67 // Ensure the given NavigationEntry has a valid state, so that WebKit does not
66 // get confused if we navigate back to it. 68 // get confused if we navigate back to it.
67 // 69 //
68 // An empty state is treated as a new navigation by WebKit, which would mean 70 // An empty state is treated as a new navigation by WebKit, which would mean
69 // losing the navigation entries and generating a new navigation entry after 71 // losing the navigation entries and generating a new navigation entry after
70 // this one. We don't want that. To avoid this we create a valid state which 72 // this one. We don't want that. To avoid this we create a valid state which
71 // WebKit will not treat as a new navigation. 73 // WebKit will not treat as a new navigation.
72 void SetPageStateIfEmpty(NavigationEntryImpl* entry) { 74 void SetPageStateIfEmpty(NavigationEntryImpl* entry) {
75 // TODO(creis): Do this for FrameNavigationEntries instead.
73 if (!entry->GetPageState().IsValid()) 76 if (!entry->GetPageState().IsValid())
74 entry->SetPageState(PageState::CreateFromURL(entry->GetURL())); 77 entry->SetPageState(PageState::CreateFromURL(entry->GetURL()));
75 } 78 }
76 79
77 NavigationEntryImpl::RestoreType ControllerRestoreTypeToEntryType( 80 NavigationEntryImpl::RestoreType ControllerRestoreTypeToEntryType(
78 NavigationController::RestoreType type) { 81 NavigationController::RestoreType type) {
79 switch (type) { 82 switch (type) {
80 case NavigationController::RESTORE_CURRENT_SESSION: 83 case NavigationController::RESTORE_CURRENT_SESSION:
81 return NavigationEntryImpl::RESTORE_CURRENT_SESSION; 84 return NavigationEntryImpl::RESTORE_CURRENT_SESSION;
82 case NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY: 85 case NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY:
83 return NavigationEntryImpl::RESTORE_LAST_SESSION_EXITED_CLEANLY; 86 return NavigationEntryImpl::RESTORE_LAST_SESSION_EXITED_CLEANLY;
84 case NavigationController::RESTORE_LAST_SESSION_CRASHED: 87 case NavigationController::RESTORE_LAST_SESSION_CRASHED:
85 return NavigationEntryImpl::RESTORE_LAST_SESSION_CRASHED; 88 return NavigationEntryImpl::RESTORE_LAST_SESSION_CRASHED;
86 } 89 }
87 NOTREACHED(); 90 NOTREACHED();
88 return NavigationEntryImpl::RESTORE_CURRENT_SESSION; 91 return NavigationEntryImpl::RESTORE_CURRENT_SESSION;
89 } 92 }
90 93
91 // Configure all the NavigationEntries in entries for restore. This resets 94 // Configure all the NavigationEntries in entries for restore. This resets
92 // the transition type to reload and makes sure the content state isn't empty. 95 // the transition type to reload and makes sure the content state isn't empty.
96 // TODO(creis): Take in a vector of FrameNavigationEntries instead.
93 void ConfigureEntriesForRestore( 97 void ConfigureEntriesForRestore(
94 std::vector<linked_ptr<NavigationEntryImpl> >* entries, 98 std::vector<linked_ptr<NavigationEntryImpl> >* entries,
95 NavigationController::RestoreType type) { 99 NavigationController::RestoreType type) {
96 for (size_t i = 0; i < entries->size(); ++i) { 100 for (size_t i = 0; i < entries->size(); ++i) {
97 // Use a transition type of reload so that we don't incorrectly increase 101 // Use a transition type of reload so that we don't incorrectly increase
98 // the typed count. 102 // the typed count.
99 (*entries)[i]->SetTransitionType(ui::PAGE_TRANSITION_RELOAD); 103 (*entries)[i]->SetTransitionType(ui::PAGE_TRANSITION_RELOAD);
100 (*entries)[i]->set_restore_type(ControllerRestoreTypeToEntryType(type)); 104 (*entries)[i]->set_restore_type(ControllerRestoreTypeToEntryType(type));
101 // NOTE(darin): This code is only needed for backwards compat. 105 // NOTE(darin): This code is only needed for backwards compat.
102 SetPageStateIfEmpty((*entries)[i].get()); 106 SetPageStateIfEmpty((*entries)[i].get());
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 178
175 // Allow the browser URL handler to rewrite the URL. This will, for example, 179 // Allow the browser URL handler to rewrite the URL. This will, for example,
176 // remove "view-source:" from the beginning of the URL to get the URL that 180 // remove "view-source:" from the beginning of the URL to get the URL that
177 // will actually be loaded. This real URL won't be shown to the user, just 181 // will actually be loaded. This real URL won't be shown to the user, just
178 // used internally. 182 // used internally.
179 GURL loaded_url(dest_url); 183 GURL loaded_url(dest_url);
180 bool reverse_on_redirect = false; 184 bool reverse_on_redirect = false;
181 BrowserURLHandlerImpl::GetInstance()->RewriteURLIfNecessary( 185 BrowserURLHandlerImpl::GetInstance()->RewriteURLIfNecessary(
182 &loaded_url, browser_context, &reverse_on_redirect); 186 &loaded_url, browser_context, &reverse_on_redirect);
183 187
188 // Common case: Navigate the top-level frame.
184 NavigationEntryImpl* entry = new NavigationEntryImpl( 189 NavigationEntryImpl* entry = new NavigationEntryImpl(
185 NULL, // The site instance for tabs is sent on navigation 190 NULL, // The site instance for tabs is sent on navigation
186 // (WebContents::GetSiteInstance). 191 // (WebContents::GetSiteInstance).
187 -1, 192 -1,
188 loaded_url, 193 loaded_url,
189 referrer, 194 referrer,
190 base::string16(), 195 base::string16(),
191 transition, 196 transition,
192 is_renderer_initiated); 197 is_renderer_initiated);
193 entry->SetVirtualURL(dest_url); 198 entry->SetVirtualURL(dest_url);
194 entry->set_user_typed_url(dest_url); 199 entry->set_user_typed_url(dest_url);
195 entry->set_update_virtual_url_with_url(reverse_on_redirect); 200 entry->set_update_virtual_url_with_url(reverse_on_redirect);
196 entry->set_extra_headers(extra_headers); 201 entry->set_extra_headers(extra_headers);
197 return entry; 202 return entry;
198 } 203 }
199 204
205 // TODO(creis): Share code with CreateNavigationEntry.
206 NavigationEntryImpl* NavigationControllerImpl::CreateSubframeNavigationEntry(
207 int64 frame_tree_node_id,
208 const GURL& url,
209 const Referrer& referrer,
210 ui::PageTransition transition,
211 bool is_renderer_initiated,
212 const std::string& extra_headers,
213 BrowserContext* browser_context) {
214 // Allow the browser URL handler to rewrite the URL. This will, for example,
215 // remove "view-source:" from the beginning of the URL to get the URL that
216 // will actually be loaded. This real URL won't be shown to the user, just
217 // used internally.
218 GURL loaded_url(url);
219 bool reverse_on_redirect = false;
220 BrowserURLHandlerImpl::GetInstance()->RewriteURLIfNecessary(
221 &loaded_url, browser_context, &reverse_on_redirect);
222
223 FrameTreeNode* main_frame = delegate_->GetFrameTreeRoot();
224
225 // Subframe navigation: Clone the current tree, then create a FrameNavEntry
226 // for the specified frame, clearing its subtree.
227 // TODO(creis): Don't clear subtree for in-page navigations.
228 NavigationEntryImpl* entry = new NavigationEntryImpl();
229 AddFramesToNavigationEntry(entry->root_node(), main_frame);
230 NavigationEntryImpl::TreeNode* node =
231 entry->GetTreeNodeForFrame(
232 main_frame->frame_tree()->FindByID(frame_tree_node_id));
233 DCHECK(node) << "Couldn't find TreeNode for " << frame_tree_node_id;
234 node->frame_entry = new FrameNavigationEntry(NULL, loaded_url, referrer);
235 node->frame_entry->set_frame_tree_node_id(frame_tree_node_id);
236 node->children.clear();
237
238 entry->SetVirtualURL(url);
239 entry->set_user_typed_url(url);
240 entry->set_update_virtual_url_with_url(reverse_on_redirect);
241 entry->set_extra_headers(extra_headers);
242 return entry;
243 }
244
200 // static 245 // static
201 void NavigationController::DisablePromptOnRepost() { 246 void NavigationController::DisablePromptOnRepost() {
202 g_check_for_repost = false; 247 g_check_for_repost = false;
203 } 248 }
204 249
205 base::Time NavigationControllerImpl::TimeSmoother::GetSmoothedTime( 250 base::Time NavigationControllerImpl::TimeSmoother::GetSmoothedTime(
206 base::Time t) { 251 base::Time t) {
207 // If |t| is between the water marks, we're in a run of duplicates 252 // If |t| is between the water marks, we're in a run of duplicates
208 // or just getting out of it, so increase the high-water mark to get 253 // or just getting out of it, so increase the high-water mark to get
209 // a time that probably hasn't been used before and return it. 254 // a time that probably hasn't been used before and return it.
(...skipping 10 matching lines...) Expand all
220 265
221 NavigationControllerImpl::NavigationControllerImpl( 266 NavigationControllerImpl::NavigationControllerImpl(
222 NavigationControllerDelegate* delegate, 267 NavigationControllerDelegate* delegate,
223 BrowserContext* browser_context) 268 BrowserContext* browser_context)
224 : browser_context_(browser_context), 269 : browser_context_(browser_context),
225 pending_entry_(NULL), 270 pending_entry_(NULL),
226 last_committed_entry_index_(-1), 271 last_committed_entry_index_(-1),
227 pending_entry_index_(-1), 272 pending_entry_index_(-1),
228 transient_entry_index_(-1), 273 transient_entry_index_(-1),
229 delegate_(delegate), 274 delegate_(delegate),
275 next_page_id_(1),
230 max_restored_page_id_(-1), 276 max_restored_page_id_(-1),
231 ssl_manager_(this), 277 ssl_manager_(this),
232 needs_reload_(false), 278 needs_reload_(false),
233 is_initial_navigation_(true), 279 is_initial_navigation_(true),
234 in_navigate_to_pending_entry_(false), 280 in_navigate_to_pending_entry_(false),
235 pending_reload_(NO_RELOAD), 281 pending_reload_(NO_RELOAD),
236 get_timestamp_callback_(base::Bind(&base::Time::Now)), 282 get_timestamp_callback_(base::Bind(&base::Time::Now)),
237 screenshot_manager_(new NavigationEntryScreenshotManager(this)) { 283 screenshot_manager_(new NavigationEntryScreenshotManager(this)) {
238 DCHECK(browser_context_); 284 DCHECK(browser_context_);
239 } 285 }
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 ReloadInternal(false, pending_reload_); 448 ReloadInternal(false, pending_reload_);
403 pending_reload_ = NO_RELOAD; 449 pending_reload_ = NO_RELOAD;
404 } 450 }
405 } 451 }
406 452
407 bool NavigationControllerImpl::IsInitialNavigation() const { 453 bool NavigationControllerImpl::IsInitialNavigation() const {
408 return is_initial_navigation_; 454 return is_initial_navigation_;
409 } 455 }
410 456
411 NavigationEntryImpl* NavigationControllerImpl::GetEntryWithPageID( 457 NavigationEntryImpl* NavigationControllerImpl::GetEntryWithPageID(
412 SiteInstance* instance, int32 page_id) const { 458 int32 page_id) const {
413 int index = GetEntryIndexWithPageID(instance, page_id); 459 int index = GetEntryIndexWithPageID(page_id);
414 return (index != -1) ? entries_[index].get() : NULL; 460 return (index != -1) ? entries_[index].get() : NULL;
415 } 461 }
416 462
417 void NavigationControllerImpl::LoadEntry(NavigationEntryImpl* entry) { 463 void NavigationControllerImpl::LoadEntry(NavigationEntryImpl* entry) {
418 // When navigating to a new page, we don't know for sure if we will actually 464 // When navigating to a new page, we don't know for sure if we will actually
419 // end up leaving the current page. The new page load could for example 465 // end up leaving the current page. The new page load could for example
420 // result in a download or a 'no content' response (e.g., a mailto: URL). 466 // result in a download or a 'no content' response (e.g., a mailto: URL).
421 SetPendingEntry(entry); 467 SetPendingEntry(entry);
422 NavigateToPendingEntry(NO_RELOAD); 468 NavigateToPendingEntry(NO_RELOAD);
423 } 469 }
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 break; 758 break;
713 case UA_OVERRIDE_FALSE: 759 case UA_OVERRIDE_FALSE:
714 override = false; 760 override = false;
715 break; 761 break;
716 default: 762 default:
717 NOTREACHED(); 763 NOTREACHED();
718 break; 764 break;
719 } 765 }
720 766
721 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( 767 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
722 CreateNavigationEntry( 768 params.frame_tree_node_id == -1 ?
723 params.url, 769 CreateNavigationEntry(
724 params.referrer, 770 params.url,
725 params.transition_type, 771 params.referrer,
726 params.is_renderer_initiated, 772 params.transition_type,
727 params.extra_headers, 773 params.is_renderer_initiated,
728 browser_context_)); 774 params.extra_headers,
729 if (params.frame_tree_node_id != -1) 775 browser_context_) :
730 entry->set_frame_tree_node_id(params.frame_tree_node_id); 776 CreateSubframeNavigationEntry(
777 params.frame_tree_node_id,
778 params.url,
779 params.referrer,
780 params.transition_type,
781 params.is_renderer_initiated,
782 params.extra_headers,
783 browser_context_));
784 // TODO(creis): Move source_site_instance to FNE.
731 entry->set_source_site_instance( 785 entry->set_source_site_instance(
732 static_cast<SiteInstanceImpl*>(params.source_site_instance.get())); 786 static_cast<SiteInstanceImpl*>(params.source_site_instance.get()));
733 if (params.redirect_chain.size() > 0) 787 if (params.redirect_chain.size() > 0)
734 entry->SetRedirectChain(params.redirect_chain); 788 entry->SetRedirectChain(params.redirect_chain);
735 // Don't allow an entry replacement if there is no entry to replace. 789 // Don't allow an entry replacement if there is no entry to replace.
736 // http://crbug.com/457149 790 // http://crbug.com/457149
737 if (params.should_replace_current_entry && entries_.size() > 0) 791 if (params.should_replace_current_entry && entries_.size() > 0)
738 entry->set_should_replace_entry(true); 792 entry->set_should_replace_entry(true);
739 entry->set_should_clear_history_list(params.should_clear_history_list); 793 entry->set_should_clear_history_list(params.should_clear_history_list);
740 entry->SetIsOverridingUserAgent(override); 794 entry->SetIsOverridingUserAgent(override);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 // We should not have a pending entry anymore. Clear it again in case any 907 // We should not have a pending entry anymore. Clear it again in case any
854 // error cases above forgot to do so. 908 // error cases above forgot to do so.
855 DiscardNonCommittedEntriesInternal(); 909 DiscardNonCommittedEntriesInternal();
856 910
857 // All committed entries should have nonempty content state so WebKit doesn't 911 // All committed entries should have nonempty content state so WebKit doesn't
858 // get confused when we go back to them (see the function for details). 912 // get confused when we go back to them (see the function for details).
859 DCHECK(params.page_state.IsValid()); 913 DCHECK(params.page_state.IsValid());
860 NavigationEntryImpl* active_entry = GetLastCommittedEntry(); 914 NavigationEntryImpl* active_entry = GetLastCommittedEntry();
861 active_entry->SetTimestamp(timestamp); 915 active_entry->SetTimestamp(timestamp);
862 active_entry->SetHttpStatusCode(params.http_status_code); 916 active_entry->SetHttpStatusCode(params.http_status_code);
863 active_entry->SetPageState(params.page_state);
864 active_entry->SetRedirectChain(params.redirects); 917 active_entry->SetRedirectChain(params.redirects);
918 FrameNavigationEntry* frame_entry =
919 active_entry->GetFrameEntryForFrame(rfh->frame_tree_node());
920 frame_entry->set_page_state(params.page_state);
865 921
866 // Use histogram to track memory impact of redirect chain because it's now 922 // Use histogram to track memory impact of redirect chain because it's now
867 // not cleared for committed entries. 923 // not cleared for committed entries.
868 size_t redirect_chain_size = 0; 924 size_t redirect_chain_size = 0;
869 for (size_t i = 0; i < params.redirects.size(); ++i) { 925 for (size_t i = 0; i < params.redirects.size(); ++i) {
870 redirect_chain_size += params.redirects[i].spec().length(); 926 redirect_chain_size += params.redirects[i].spec().length();
871 } 927 }
872 UMA_HISTOGRAM_COUNTS("Navigation.RedirectChainSize", redirect_chain_size); 928 UMA_HISTOGRAM_COUNTS("Navigation.RedirectChainSize", redirect_chain_size);
873 929
874 // Once it is committed, we no longer need to track several pieces of state on 930 // Once it is committed, we no longer need to track several pieces of state on
875 // the entry. 931 // the entry.
876 active_entry->ResetForCommit(); 932 active_entry->ResetForCommit();
877 933
878 // The active entry's SiteInstance should match our SiteInstance. 934 // The active entry's SiteInstance should match our SiteInstance.
879 // TODO(creis): This check won't pass for subframes until we create entries 935 CHECK(frame_entry->site_instance() == rfh->GetSiteInstance());
880 // for subframe navigations.
881 if (ui::PageTransitionIsMainFrame(params.transition))
882 CHECK(active_entry->site_instance() == rfh->GetSiteInstance());
883 936
884 // Remember the bindings the renderer process has at this point, so that 937 // Remember the bindings the renderer process has at this point, so that
885 // we do not grant this entry additional bindings if we come back to it. 938 // we do not grant this entry additional bindings if we come back to it.
886 active_entry->SetBindings(rfh->GetEnabledBindings()); 939 active_entry->SetBindings(rfh->GetEnabledBindings());
887 940
888 // Now prep the rest of the details for the notification and broadcast. 941 // Now prep the rest of the details for the notification and broadcast.
889 details->entry = active_entry; 942 details->entry = active_entry;
890 details->is_main_frame = 943 details->is_main_frame =
891 ui::PageTransitionIsMainFrame(params.transition); 944 ui::PageTransitionIsMainFrame(params.transition);
892 details->serialized_security_info = params.security_info; 945 details->serialized_security_info = params.security_info;
893 details->http_status_code = params.http_status_code; 946 details->http_status_code = params.http_status_code;
894 NotifyNavigationEntryCommitted(details); 947 NotifyNavigationEntryCommitted(details);
895 948
896 return true; 949 return true;
897 } 950 }
898 951
899 NavigationType NavigationControllerImpl::ClassifyNavigation( 952 NavigationType NavigationControllerImpl::ClassifyNavigation(
900 RenderFrameHostImpl* rfh, 953 RenderFrameHostImpl* rfh,
901 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const { 954 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const {
902 if (params.page_id == -1) { 955 // TODO(creis): Can this go away? We now have page_id == -1 for all new navs.
903 // TODO(nasko, creis): An out-of-process child frame has no way of 956 if (params.item_sequence_number == -1) {
904 // knowing the page_id of its parent, so it is passing back -1. The
905 // semantics here should be re-evaluated during session history refactor
906 // (see http://crbug.com/236848). For now, we assume this means the
907 // child frame loaded and proceed. Note that this may do the wrong thing
908 // for cross-process AUTO_SUBFRAME navigations.
909 if (rfh->IsCrossProcessSubframe())
910 return NAVIGATION_TYPE_NEW_SUBFRAME;
911
912 // The renderer generates the page IDs, and so if it gives us the invalid 957 // The renderer generates the page IDs, and so if it gives us the invalid
913 // page ID (-1) we know it didn't actually navigate. This happens in a few 958 // page ID (-1) we know it didn't actually navigate. This happens in a few
914 // cases: 959 // cases:
915 // 960 //
916 // - If a page makes a popup navigated to about blank, and then writes 961 // - If a page makes a popup navigated to about blank, and then writes
917 // stuff like a subframe navigated to a real page. We'll get the commit 962 // stuff like a subframe navigated to a real page. We'll get the commit
918 // for the subframe, but there won't be any commit for the outer page. 963 // for the subframe, but there won't be any commit for the outer page.
919 // 964 //
920 // - We were also getting these for failed loads (for example, bug 21849). 965 // - We were also getting these for failed loads (for example, bug 21849).
921 // The guess is that we get a "load commit" for the alternate error page, 966 // The guess is that we get a "load commit" for the alternate error page,
922 // but that doesn't affect the page ID, so we get the "old" one, which 967 // but that doesn't affect the page ID, so we get the "old" one, which
923 // could be invalid. This can also happen for a cross-site transition 968 // could be invalid. This can also happen for a cross-site transition
924 // that causes us to swap processes. Then the error page load will be in 969 // that causes us to swap processes. Then the error page load will be in
925 // a new process with no page IDs ever assigned (and hence a -1 value), 970 // a new process with no page IDs ever assigned (and hence a -1 value),
926 // yet the navigation controller still might have previous pages in its 971 // yet the navigation controller still might have previous pages in its
927 // list. 972 // list.
928 // 973 //
929 // In these cases, there's nothing we can do with them, so ignore. 974 // In these cases, there's nothing we can do with them, so ignore.
930 return NAVIGATION_TYPE_NAV_IGNORE; 975 return NAVIGATION_TYPE_NAV_IGNORE;
931 } 976 }
932 977
933 if (params.page_id > delegate_->GetMaxPageIDForSiteInstance( 978 if (params.page_id == -1) {
934 rfh->GetSiteInstance())) { 979 // A page ID of -1 means this is a new navigation of some kind.
980 // TODO(creis): update comment below.
935 // Greater page IDs than we've ever seen before are new pages. We may or may 981 // Greater page IDs than we've ever seen before are new pages. We may or may
936 // not have a pending entry for the page, and this may or may not be the 982 // not have a pending entry for the page, and this may or may not be the
937 // main frame. 983 // main frame.
938 if (ui::PageTransitionIsMainFrame(params.transition)) 984 if (ui::PageTransitionIsMainFrame(params.transition))
939 return NAVIGATION_TYPE_NEW_PAGE; 985 return NAVIGATION_TYPE_NEW_PAGE;
940 986
941 // When this is a new subframe navigation, we should have a committed page 987 // When this is a new subframe navigation, we should have a committed page
942 // for which it's a suframe in. This may not be the case when an iframe is 988 // for which it's a suframe in. This may not be the case when an iframe is
943 // navigated on a popup navigated to about:blank (the iframe would be 989 // navigated on a popup navigated to about:blank (the iframe would be
944 // written into the popup by script on the main page). For these cases, 990 // written into the popup by script on the main page). For these cases,
945 // there isn't any navigation stuff we can do, so just ignore it. 991 // there isn't any navigation stuff we can do, so just ignore it.
946 if (!GetLastCommittedEntry()) 992 if (!GetLastCommittedEntry())
947 return NAVIGATION_TYPE_NAV_IGNORE; 993 return NAVIGATION_TYPE_NAV_IGNORE;
948 994
949 // Valid subframe navigation. 995 // Valid subframe navigation.
996 // TODO(creis): Do this once 464014 is fixed.
997 //if (ui::PageTransitionCoreTypeIs(params.transition,
998 // ui::PAGE_TRANSITION_AUTO_SUBFRAME))
999 // return NAVIGATION_TYPE_AUTO_SUBFRAME;
950 return NAVIGATION_TYPE_NEW_SUBFRAME; 1000 return NAVIGATION_TYPE_NEW_SUBFRAME;
951 } 1001 }
952 1002
953 // We only clear the session history when navigating to a new page. 1003 // We only clear the session history when navigating to a new page.
954 DCHECK(!params.history_list_was_cleared); 1004 DCHECK(!params.history_list_was_cleared);
955 1005
956 // Now we know that the notification is for an existing page. Find that entry. 1006 // Now we know that the notification is for an existing page. Find that entry.
957 int existing_entry_index = GetEntryIndexWithPageID( 1007 int existing_entry_index = GetEntryIndexWithPageID(params.page_id);
958 rfh->GetSiteInstance(),
959 params.page_id);
960 if (existing_entry_index == -1) { 1008 if (existing_entry_index == -1) {
961 // The page was not found. It could have been pruned because of the limit on 1009 // The page was not found. It could have been pruned because of the limit on
962 // back/forward entries (not likely since we'll usually tell it to navigate 1010 // back/forward entries (not likely since we'll usually tell it to navigate
963 // to such entries). It could also mean that the renderer is smoking crack. 1011 // to such entries). It could also mean that the renderer is smoking crack.
964 NOTREACHED(); 1012 NOTREACHED();
965 1013
966 // Because the unknown entry has committed, we risk showing the wrong URL in 1014 // Because the unknown entry has committed, we risk showing the wrong URL in
967 // release builds. Instead, we'll kill the renderer process to be safe. 1015 // release builds. Instead, we'll kill the renderer process to be safe.
968 LOG(ERROR) << "terminating renderer for bad navigation: " << params.url; 1016 LOG(ERROR) << "terminating renderer for bad navigation: " << params.url;
969 RecordAction(base::UserMetricsAction("BadMessageTerminate_NC")); 1017 RecordAction(base::UserMetricsAction("BadMessageTerminate_NC"));
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1036 // Since we weeded out "new" navigations above, we know this is an existing 1084 // Since we weeded out "new" navigations above, we know this is an existing
1037 // (back/forward) navigation. 1085 // (back/forward) navigation.
1038 return NAVIGATION_TYPE_EXISTING_PAGE; 1086 return NAVIGATION_TYPE_EXISTING_PAGE;
1039 } 1087 }
1040 1088
1041 void NavigationControllerImpl::RendererDidNavigateToNewPage( 1089 void NavigationControllerImpl::RendererDidNavigateToNewPage(
1042 RenderFrameHostImpl* rfh, 1090 RenderFrameHostImpl* rfh,
1043 const FrameHostMsg_DidCommitProvisionalLoad_Params& params, 1091 const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
1044 bool replace_entry) { 1092 bool replace_entry) {
1045 NavigationEntryImpl* new_entry; 1093 NavigationEntryImpl* new_entry;
1094 FrameNavigationEntry* new_frame_entry;
1046 bool update_virtual_url; 1095 bool update_virtual_url;
1047 // Only make a copy of the pending entry if it is appropriate for the new page 1096 // Only make a copy of the pending entry if it is appropriate for the new page
1048 // that was just loaded. We verify this at a coarse grain by checking that 1097 // that was just loaded. We verify this at a coarse grain by checking that
1049 // the SiteInstance hasn't been assigned to something else. 1098 // the SiteInstance hasn't been assigned to something else.
1050 if (pending_entry_ && 1099 // TODO(creis): Copy over details from pending entry when appropriate.
1051 (!pending_entry_->site_instance() || 1100 // (Do we need a pending entry for each frame?)
1052 pending_entry_->site_instance() == rfh->GetSiteInstance())) { 1101 /*FrameNavigationEntryImpl* pending_entry = ...;
1053 new_entry = pending_entry_->Clone(); 1102 if (pending_entry &&
1103 (!pending_entry_>site_instance() ||
1104 pending_entry->site_instance() == rfh->GetSiteInstance())) {
1105 new_entry = new FrameNavigationEntryImpl(*pending_entry);
1054 1106
1055 update_virtual_url = new_entry->update_virtual_url_with_url(); 1107 update_virtual_url = new_entry->update_virtual_url_with_url();
1056 } else { 1108 } else { */
1057 new_entry = new NavigationEntryImpl; 1109 new_entry = new NavigationEntryImpl;
1110 new_frame_entry = new FrameNavigationEntry;
1111 int64 frame_tree_node_id = rfh->frame_tree_node()->frame_tree_node_id();
1112 new_frame_entry->set_frame_tree_node_id(frame_tree_node_id);
1058 1113
1059 // Find out whether the new entry needs to update its virtual URL on URL 1114 // Find out whether the new entry needs to update its virtual URL on URL
1060 // change and set up the entry accordingly. This is needed to correctly 1115 // change and set up the entry accordingly. This is needed to correctly
1061 // update the virtual URL when replaceState is called after a pushState. 1116 // update the virtual URL when replaceState is called after a pushState.
1062 GURL url = params.url; 1117 GURL url = params.url;
1063 bool needs_update = false; 1118 bool needs_update = false;
1064 BrowserURLHandlerImpl::GetInstance()->RewriteURLIfNecessary( 1119 BrowserURLHandlerImpl::GetInstance()->RewriteURLIfNecessary(
1065 &url, browser_context_, &needs_update); 1120 &url, browser_context_, &needs_update);
1066 new_entry->set_update_virtual_url_with_url(needs_update); 1121 new_entry->set_update_virtual_url_with_url(needs_update);
1067 1122
1068 // When navigating to a new page, give the browser URL handler a chance to 1123 // When navigating to a new page, give the browser URL handler a chance to
1069 // update the virtual URL based on the new URL. For example, this is needed 1124 // update the virtual URL based on the new URL. For example, this is needed
1070 // to show chrome://bookmarks/#1 when the bookmarks webui extension changes 1125 // to show chrome://bookmarks/#1 when the bookmarks webui extension changes
1071 // the URL. 1126 // the URL.
1072 update_virtual_url = needs_update; 1127 update_virtual_url = needs_update;
1073 } 1128 //}
1074 1129
1075 // Don't use the page type from the pending entry. Some interstitial page 1130 // Don't use the page type from the pending entry. Some interstitial page
1076 // may have set the type to interstitial. Once we commit, however, the page 1131 // may have set the type to interstitial. Once we commit, however, the page
1077 // type must always be normal or error. 1132 // type must always be normal or error.
1133 // TODO(creis): Move page type to FNE.
1078 new_entry->set_page_type(params.url_is_unreachable ? PAGE_TYPE_ERROR 1134 new_entry->set_page_type(params.url_is_unreachable ? PAGE_TYPE_ERROR
1079 : PAGE_TYPE_NORMAL); 1135 : PAGE_TYPE_NORMAL);
1080 new_entry->SetURL(params.url); 1136 new_frame_entry->set_url(params.url);
1081 if (update_virtual_url) 1137 if (update_virtual_url)
1082 UpdateVirtualURLToURL(new_entry, params.url); 1138 UpdateVirtualURLToURL(new_entry, params.url);
1083 new_entry->SetReferrer(params.referrer); 1139 new_frame_entry->set_referrer(params.referrer);
1084 new_entry->SetPageID(params.page_id); 1140 new_frame_entry->set_site_instance(rfh->GetSiteInstance());
1141 new_frame_entry->set_item_sequence_number(params.item_sequence_number);
1142 new_frame_entry->set_document_sequence_number(
1143 params.document_sequence_number);
1144
1145 // Use a new page ID for this entry.
1146 CHECK_EQ(-1, params.page_id);
1147 new_entry->SetPageID(next_page_id_++);
1148
1085 new_entry->SetTransitionType(params.transition); 1149 new_entry->SetTransitionType(params.transition);
1086 new_entry->set_site_instance(
1087 static_cast<SiteInstanceImpl*>(rfh->GetSiteInstance()));
1088 new_entry->SetHasPostData(params.is_post); 1150 new_entry->SetHasPostData(params.is_post);
1089 new_entry->SetPostID(params.post_id); 1151 new_entry->SetPostID(params.post_id);
1090 new_entry->SetOriginalRequestURL(params.original_request_url); 1152 new_entry->SetOriginalRequestURL(params.original_request_url);
1091 new_entry->SetIsOverridingUserAgent(params.is_overriding_user_agent); 1153 new_entry->SetIsOverridingUserAgent(params.is_overriding_user_agent);
1092 1154
1093 // history.pushState() is classified as a navigation to a new page, but 1155 // history.pushState() is classified as a navigation to a new page, but
1094 // sets was_within_same_page to true. In this case, we already have the 1156 // sets was_within_same_page to true. In this case, we already have the
1095 // title and favicon available, so set them immediately. 1157 // title and favicon available, so set them immediately.
1096 if (params.was_within_same_page && GetLastCommittedEntry()) { 1158 if (params.was_within_same_page && GetLastCommittedEntry()) {
1097 new_entry->SetTitle(GetLastCommittedEntry()->GetTitle()); 1159 new_entry->SetTitle(GetLastCommittedEntry()->GetTitle());
1098 new_entry->GetFavicon() = GetLastCommittedEntry()->GetFavicon(); 1160 new_entry->GetFavicon() = GetLastCommittedEntry()->GetFavicon();
1099 } 1161 }
1100 1162
1101 DCHECK(!params.history_list_was_cleared || !replace_entry); 1163 DCHECK(!params.history_list_was_cleared || !replace_entry);
1102 // The browser requested to clear the session history when it initiated the 1164 // The browser requested to clear the session history when it initiated the
1103 // navigation. Now we know that the renderer has updated its state accordingly 1165 // navigation. Now we know that the renderer has updated its state accordingly
1104 // and it is safe to also clear the browser side history. 1166 // and it is safe to also clear the browser side history.
1105 if (params.history_list_was_cleared) { 1167 if (params.history_list_was_cleared) {
1106 DiscardNonCommittedEntriesInternal(); 1168 DiscardNonCommittedEntriesInternal();
1107 entries_.clear(); 1169 entries_.clear();
1108 last_committed_entry_index_ = -1; 1170 last_committed_entry_index_ = -1;
1171 rfh->frame_tree_node()->set_last_committed_frame_entry(nullptr);
1109 } 1172 }
1110 1173
1111 InsertOrReplaceEntry(new_entry, replace_entry); 1174 InsertOrReplaceEntry(rfh, new_entry, new_frame_entry, replace_entry);
1112 } 1175 }
1113 1176
1114 void NavigationControllerImpl::RendererDidNavigateToExistingPage( 1177 void NavigationControllerImpl::RendererDidNavigateToExistingPage(
1115 RenderFrameHostImpl* rfh, 1178 RenderFrameHostImpl* rfh,
1116 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { 1179 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
1117 // We should only get here for main frame navigations. 1180 // We should only get here for main frame navigations.
1118 DCHECK(ui::PageTransitionIsMainFrame(params.transition)); 1181 DCHECK(ui::PageTransitionIsMainFrame(params.transition));
1119 1182
1120 // This is a back/forward navigation. The existing page for the ID is 1183 // This is a back/forward navigation. The existing page for the ID is
1121 // guaranteed to exist by ClassifyNavigation, and we just need to update it 1184 // guaranteed to exist by ClassifyNavigation, and we just need to update it
1122 // with new information from the renderer. 1185 // with new information from the renderer.
1123 int entry_index = GetEntryIndexWithPageID(rfh->GetSiteInstance(), 1186 int entry_index = GetEntryIndexWithPageID(params.page_id);
1124 params.page_id);
1125 DCHECK(entry_index >= 0 && 1187 DCHECK(entry_index >= 0 &&
1126 entry_index < static_cast<int>(entries_.size())); 1188 entry_index < static_cast<int>(entries_.size()));
1127 NavigationEntryImpl* entry = entries_[entry_index].get(); 1189 NavigationEntryImpl* entry = entries_[entry_index].get();
1128 1190
1191 // TODO(creis): Do these operations directly on the FNE.
1129 // The URL may have changed due to redirects. 1192 // The URL may have changed due to redirects.
1130 entry->set_page_type(params.url_is_unreachable ? PAGE_TYPE_ERROR 1193 entry->set_page_type(params.url_is_unreachable ? PAGE_TYPE_ERROR
1131 : PAGE_TYPE_NORMAL); 1194 : PAGE_TYPE_NORMAL);
1132 entry->SetURL(params.url); 1195 entry->SetURL(params.url);
1133 entry->SetReferrer(params.referrer); 1196 entry->SetReferrer(params.referrer);
1134 if (entry->update_virtual_url_with_url()) 1197 if (entry->update_virtual_url_with_url())
1135 UpdateVirtualURLToURL(entry, params.url); 1198 UpdateVirtualURLToURL(entry, params.url);
1136 1199
1137 // The redirected to page should not inherit the favicon from the previous 1200 // The redirected to page should not inherit the favicon from the previous
1138 // page. 1201 // page.
1139 if (ui::PageTransitionIsRedirect(params.transition)) 1202 if (ui::PageTransitionIsRedirect(params.transition))
1140 entry->GetFavicon() = FaviconStatus(); 1203 entry->GetFavicon() = FaviconStatus();
1141 1204
1142 // The site instance will normally be the same except during session restore, 1205 // The site instance will normally be the same except during session restore,
1143 // when no site instance will be assigned. 1206 // when no site instance will be assigned.
1144 DCHECK(entry->site_instance() == NULL || 1207 DCHECK(entry->site_instance() == NULL ||
1145 entry->site_instance() == rfh->GetSiteInstance()); 1208 entry->site_instance() == rfh->GetSiteInstance());
1146 entry->set_site_instance( 1209 entry->set_site_instance(rfh->GetSiteInstance());
1147 static_cast<SiteInstanceImpl*>(rfh->GetSiteInstance()));
1148 1210
1149 entry->SetHasPostData(params.is_post); 1211 entry->SetHasPostData(params.is_post);
1150 entry->SetPostID(params.post_id); 1212 entry->SetPostID(params.post_id);
1151 1213
1152 // The entry we found in the list might be pending if the user hit 1214 // The entry we found in the list might be pending if the user hit
1153 // back/forward/reload. This load should commit it (since it's already in the 1215 // back/forward/reload. This load should commit it (since it's already in the
1154 // list, we can just discard the pending pointer). We should also discard the 1216 // list, we can just discard the pending pointer). We should also discard the
1155 // pending entry if it corresponds to a different navigation, since that one 1217 // pending entry if it corresponds to a different navigation, since that one
1156 // is now likely canceled. If it is not canceled, we will treat it as a new 1218 // is now likely canceled. If it is not canceled, we will treat it as a new
1157 // navigation when it arrives, which is also ok. 1219 // navigation when it arrives, which is also ok.
1158 // 1220 //
1159 // Note that we need to use the "internal" version since we don't want to 1221 // Note that we need to use the "internal" version since we don't want to
1160 // actually change any other state, just kill the pointer. 1222 // actually change any other state, just kill the pointer.
1161 DiscardNonCommittedEntriesInternal(); 1223 DiscardNonCommittedEntriesInternal();
1162 1224
1163 // If a transient entry was removed, the indices might have changed, so we 1225 // If a transient entry was removed, the indices might have changed, so we
1164 // have to query the entry index again. 1226 // have to query the entry index again.
1165 last_committed_entry_index_ = 1227 last_committed_entry_index_ = GetEntryIndexWithPageID(params.page_id);
1166 GetEntryIndexWithPageID(rfh->GetSiteInstance(), params.page_id); 1228 rfh->frame_tree_node()->set_last_committed_frame_entry(
1229 entry->GetFrameEntryForFrame(rfh->frame_tree_node()));
1167 } 1230 }
1168 1231
1169 void NavigationControllerImpl::RendererDidNavigateToSamePage( 1232 void NavigationControllerImpl::RendererDidNavigateToSamePage(
1170 RenderFrameHostImpl* rfh, 1233 RenderFrameHostImpl* rfh,
1171 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { 1234 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
1172 // This mode implies we have a pending entry that's the same as an existing 1235 // This mode implies we have a pending entry that's the same as an existing
1173 // entry for this page ID. This entry is guaranteed to exist by 1236 // entry for this page ID. This entry is guaranteed to exist by
1174 // ClassifyNavigation. All we need to do is update the existing entry. 1237 // ClassifyNavigation. All we need to do is update the existing entry.
1175 NavigationEntryImpl* existing_entry = GetEntryWithPageID( 1238 NavigationEntryImpl* existing_entry = GetEntryWithPageID(params.page_id);
1176 rfh->GetSiteInstance(), params.page_id);
1177 1239
1178 // We assign the entry's unique ID to be that of the new one. Since this is 1240 // We assign the entry's unique ID to be that of the new one. Since this is
1179 // always the result of a user action, we want to dismiss infobars, etc. like 1241 // always the result of a user action, we want to dismiss infobars, etc. like
1180 // a regular user-initiated navigation. 1242 // a regular user-initiated navigation.
1181 existing_entry->set_unique_id(pending_entry_->GetUniqueID()); 1243 existing_entry->set_unique_id(pending_entry_->GetUniqueID());
1182 1244
1183 // The URL may have changed due to redirects. 1245 // The URL may have changed due to redirects.
1184 existing_entry->set_page_type(params.url_is_unreachable ? PAGE_TYPE_ERROR 1246 existing_entry->set_page_type(params.url_is_unreachable ? PAGE_TYPE_ERROR
1185 : PAGE_TYPE_NORMAL); 1247 : PAGE_TYPE_NORMAL);
1186 if (existing_entry->update_virtual_url_with_url()) 1248 if (existing_entry->update_virtual_url_with_url())
1187 UpdateVirtualURLToURL(existing_entry, params.url); 1249 UpdateVirtualURLToURL(existing_entry, params.url);
1188 existing_entry->SetURL(params.url); 1250 existing_entry->SetURL(params.url);
1189 existing_entry->SetReferrer(params.referrer); 1251 existing_entry->SetReferrer(params.referrer);
1190 1252
1191 // The page may have been requested with a different HTTP method. 1253 // The page may have been requested with a different HTTP method.
1192 existing_entry->SetHasPostData(params.is_post); 1254 existing_entry->SetHasPostData(params.is_post);
1193 existing_entry->SetPostID(params.post_id); 1255 existing_entry->SetPostID(params.post_id);
1194 1256
1195 DiscardNonCommittedEntries(); 1257 DiscardNonCommittedEntries();
1196 } 1258 }
1197 1259
1198 void NavigationControllerImpl::RendererDidNavigateInPage( 1260 void NavigationControllerImpl::RendererDidNavigateInPage(
1199 RenderFrameHostImpl* rfh, 1261 RenderFrameHostImpl* rfh,
1200 const FrameHostMsg_DidCommitProvisionalLoad_Params& params, 1262 const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
1201 bool* did_replace_entry) { 1263 bool* did_replace_entry) {
1264 // TODO(creis): Why? Is this by spec?
1202 DCHECK(ui::PageTransitionIsMainFrame(params.transition)) << 1265 DCHECK(ui::PageTransitionIsMainFrame(params.transition)) <<
1203 "WebKit should only tell us about in-page navs for the main frame."; 1266 "WebKit should only tell us about in-page navs for the main frame.";
1204 // We're guaranteed to have an entry for this one. 1267 // We're guaranteed to have an entry for this one.
1205 NavigationEntryImpl* existing_entry = GetEntryWithPageID( 1268 NavigationEntryImpl* existing_entry = GetEntryWithPageID(params.page_id);
1206 rfh->GetSiteInstance(), params.page_id);
1207 1269
1208 // Reference fragment navigation. We're guaranteed to have the last_committed 1270 // Reference fragment navigation. We're guaranteed to have the last_committed
1209 // entry and it will be the same page as the new navigation (minus the 1271 // entry and it will be the same page as the new navigation (minus the
1210 // reference fragments, of course). We'll update the URL of the existing 1272 // reference fragments, of course). We'll update the URL of the existing
1211 // entry without pruning the forward history. 1273 // entry without pruning the forward history.
1212 existing_entry->set_page_type(params.url_is_unreachable ? PAGE_TYPE_ERROR 1274 existing_entry->set_page_type(params.url_is_unreachable ? PAGE_TYPE_ERROR
1213 : PAGE_TYPE_NORMAL); 1275 : PAGE_TYPE_NORMAL);
1214 existing_entry->SetURL(params.url); 1276 existing_entry->SetURL(params.url);
1215 if (existing_entry->update_virtual_url_with_url()) 1277 if (existing_entry->update_virtual_url_with_url())
1216 UpdateVirtualURLToURL(existing_entry, params.url); 1278 UpdateVirtualURLToURL(existing_entry, params.url);
1217 1279
1218 existing_entry->SetHasPostData(params.is_post); 1280 existing_entry->SetHasPostData(params.is_post);
1219 existing_entry->SetPostID(params.post_id); 1281 existing_entry->SetPostID(params.post_id);
1220 1282
1221 // This replaces the existing entry since the page ID didn't change. 1283 // This replaces the existing entry since the page ID didn't change.
1222 *did_replace_entry = true; 1284 *did_replace_entry = true;
1223 1285
1224 DiscardNonCommittedEntriesInternal(); 1286 DiscardNonCommittedEntriesInternal();
1225 1287
1226 // If a transient entry was removed, the indices might have changed, so we 1288 // If a transient entry was removed, the indices might have changed, so we
1227 // have to query the entry index again. 1289 // have to query the entry index again.
1228 last_committed_entry_index_ = 1290 last_committed_entry_index_ = GetEntryIndexWithPageID(params.page_id);
1229 GetEntryIndexWithPageID(rfh->GetSiteInstance(), params.page_id); 1291 rfh->frame_tree_node()->set_last_committed_frame_entry(
1292 existing_entry->GetFrameEntryForFrame(rfh->frame_tree_node()));
1230 } 1293 }
1231 1294
1232 void NavigationControllerImpl::RendererDidNavigateNewSubframe( 1295 void NavigationControllerImpl::RendererDidNavigateNewSubframe(
1233 RenderFrameHostImpl* rfh, 1296 RenderFrameHostImpl* rfh,
1234 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { 1297 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
1235 if (!ui::PageTransitionCoreTypeIs(params.transition, 1298 int64 frame_tree_node_id = rfh->frame_tree_node()->frame_tree_node_id();
1236 ui::PAGE_TRANSITION_MANUAL_SUBFRAME)) { 1299 // TODO(creis): Is this equivalent to checking PAGE_TRANSITION_AUTO_SUBFRAME?
1300 if (!rfh->frame_tree_node()->last_committed_frame_entry()) {
1301 DCHECK(ui::PageTransitionCoreTypeIs(params.transition,
1302 ui::PAGE_TRANSITION_AUTO_SUBFRAME));
1237 // There was a comment here that said, "This is not user-initiated. Ignore." 1303 // There was a comment here that said, "This is not user-initiated. Ignore."
1238 // But this makes no sense; non-user-initiated navigations should be 1304 // But this makes no sense; non-user-initiated navigations should be
1239 // determined to be of type NAVIGATION_TYPE_AUTO_SUBFRAME and sent to 1305 // determined to be of type NAVIGATION_TYPE_AUTO_SUBFRAME and sent to
1240 // RendererDidNavigateAutoSubframe below. 1306 // RendererDidNavigateAutoSubframe below.
1241 // 1307 //
1242 // This if clause dates back to https://codereview.chromium.org/115919 and 1308 // This if clause dates back to https://codereview.chromium.org/115919 and
1243 // the handling of immediate redirects. TODO(avi): Is this still valid? I'm 1309 // the handling of immediate redirects. TODO(avi): Is this still valid? I'm
1244 // pretty sure that's there's nothing left of that code and that we should 1310 // pretty sure that's there's nothing left of that code and that we should
1245 // take this out. 1311 // take this out.
1246 // 1312 //
1247 // Except for cross-process iframes; this doesn't work yet for them. 1313 // Except for cross-process iframes; this doesn't work yet for them.
1248 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( 1314 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1249 switches::kSitePerProcess)) { 1315 switches::kSitePerProcess)) {
1250 NOTREACHED(); 1316 NOTREACHED();
1251 } 1317 }
1252 1318
1253 DiscardNonCommittedEntriesInternal(); 1319 DiscardNonCommittedEntriesInternal();
1320
1321 // New: We do need to add a FrameNavigationEntry.
1322 // TODO(creis): Refactor this method to avoid duplication.
1323 FrameNavigationEntry* frame_entry = new FrameNavigationEntry(
1324 rfh->GetSiteInstance(), params.url, params.referrer);
1325 frame_entry->set_frame_tree_node_id(frame_tree_node_id);
1326 frame_entry->set_item_sequence_number(params.item_sequence_number);
1327 frame_entry->set_document_sequence_number(params.document_sequence_number);
1328 rfh->frame_tree_node()->set_last_committed_frame_entry(frame_entry);
1329
1330 // Reset the frame tree pointers for the last committed entry.
1331 NavigationEntryImpl* last_committed =
1332 NavigationEntryImpl::FromNavigationEntry(GetLastCommittedEntry());
1333 // TODO(creis): Just add this one; don't try to reset the whole tree.
1334 last_committed->ResetFrameTree();
1335 AddFramesToNavigationEntry(last_committed->root_node(),
1336 delegate_->GetFrameTreeRoot());
1337
1254 return; 1338 return;
1255 } 1339 }
1256 1340
1257 // Manual subframe navigations just get the current entry cloned so the user 1341 // Manual subframe navigations just get the current entry cloned so the user
1258 // can go back or forward to it. The actual subframe information will be 1342 // can go back or forward to it. The actual subframe information will be
1259 // stored in the page state for each of those entries. This happens out of 1343 // stored in the page state for each of those entries. This happens out of
1260 // band with the actual navigations. 1344 // band with the actual navigations.
1261 DCHECK(GetLastCommittedEntry()) << "ClassifyNavigation should guarantee " 1345 DCHECK(GetLastCommittedEntry()) << "ClassifyNavigation should guarantee "
1262 << "that a last committed entry exists."; 1346 << "that a last committed entry exists.";
1263 NavigationEntryImpl* new_entry = GetLastCommittedEntry()->Clone(); 1347 NavigationEntryImpl* new_entry = GetLastCommittedEntry()->Clone();
1264 new_entry->SetPageID(params.page_id); 1348
1265 InsertOrReplaceEntry(new_entry, false); 1349 // Use a new page ID for this entry.
1350 CHECK_EQ(-1, params.page_id);
1351 new_entry->SetPageID(next_page_id_++);
1352
1353 // Create an appropriate subframe entry for it.
1354 FrameNavigationEntry* frame_entry = new FrameNavigationEntry(
1355 rfh->GetSiteInstance(), params.url, params.referrer);
1356 frame_entry->set_frame_tree_node_id(frame_tree_node_id);
1357 frame_entry->set_item_sequence_number(params.item_sequence_number);
1358 frame_entry->set_document_sequence_number(params.document_sequence_number);
1359
1360 InsertOrReplaceEntry(rfh, new_entry, frame_entry, false);
1266 } 1361 }
1267 1362
1268 bool NavigationControllerImpl::RendererDidNavigateAutoSubframe( 1363 bool NavigationControllerImpl::RendererDidNavigateAutoSubframe(
1269 RenderFrameHostImpl* rfh, 1364 RenderFrameHostImpl* rfh,
1270 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { 1365 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
1271 DCHECK(ui::PageTransitionCoreTypeIs(params.transition, 1366 DCHECK(ui::PageTransitionCoreTypeIs(params.transition,
1272 ui::PAGE_TRANSITION_AUTO_SUBFRAME)); 1367 ui::PAGE_TRANSITION_AUTO_SUBFRAME));
1273 1368
1274 // We're guaranteed to have a previously committed entry, and we now need to 1369 // We're guaranteed to have a previously committed entry, and we now need to
1275 // handle navigation inside of a subframe in it without creating a new entry. 1370 // handle navigation inside of a subframe in it without creating a new entry.
1276 DCHECK(GetLastCommittedEntry()); 1371 DCHECK(GetLastCommittedEntry());
1277 1372
1278 // Handle the case where we're navigating back/forward to a previous subframe 1373 // TODO(creis): Split this out into ExistingSubframe.
1279 // navigation entry. This is case "2." in NAV_AUTO_SUBFRAME comment in the 1374 // Handle the case where we're navigating back/forward to a previous
1280 // header file. In case "1." this will be a NOP. 1375 // subframe navigation entry. This is case "2." in NAV_AUTO_SUBFRAME comment
1281 int entry_index = GetEntryIndexWithPageID( 1376 // in the header file. In case "1." this will be a NOP.
1282 rfh->GetSiteInstance(), 1377 int entry_index = GetEntryIndexWithPageID(params.page_id);
1283 params.page_id); 1378 if (entry_index < 0 || entry_index >= static_cast<int>(entries_.size())) {
1284 if (entry_index < 0 ||
1285 entry_index >= static_cast<int>(entries_.size())) {
1286 NOTREACHED(); 1379 NOTREACHED();
1287 return false; 1380 return false;
1288 } 1381 }
1289 1382
1290 // Update the current navigation entry in case we're going back/forward. 1383 // Update the current navigation entry in case we're going back/forward.
1291 if (entry_index != last_committed_entry_index_) { 1384 if (entry_index != last_committed_entry_index_) {
1292 last_committed_entry_index_ = entry_index; 1385 last_committed_entry_index_ = entry_index;
1293 DiscardNonCommittedEntriesInternal(); 1386 DiscardNonCommittedEntriesInternal();
1387
1388 // New: Find the FrameNavigationEntry this corresponds to and update our
1389 // index for that frame.
1390 // TODO(creis): Update the FNE, similar to ExistingPage.
1391 NavigationEntryImpl* entry = GetEntryAtIndex(entry_index);
1392 FrameNavigationEntry* frame_entry =
1393 entry->GetFrameEntryForFrame(rfh->frame_tree_node());
1394 rfh->frame_tree_node()->set_last_committed_frame_entry(frame_entry);
1395
1294 return true; 1396 return true;
1295 } 1397 }
1296 1398
1399 // If we get here without returning, then this was a second (or greater)
1400 // subframe committing as part of a back/forward. Only the first one causes
1401 // us to change the last_committed_entry_index_.
1402
1403 // New: We do need to add a FrameNavigationEntry.
1404 FrameNavigationEntry* frame_entry = new FrameNavigationEntry(
1405 rfh->GetSiteInstance(), params.url, params.referrer);
1406 int64 frame_tree_node_id = rfh->frame_tree_node()->frame_tree_node_id();
1407 frame_entry->set_frame_tree_node_id(frame_tree_node_id);
1408 frame_entry->set_item_sequence_number(params.item_sequence_number);
1409 frame_entry->set_document_sequence_number(params.document_sequence_number);
1410
1411 // TODO(creis): This was missing in the case of going forward from an old main
1412 // frame to one with a subframe. We don't give the re-created subframe the
1413 // same FTN ID, so we don't find it in our array. (That's a bug on its own.)
1414 // But when we do get here legitimately, don't we need to assign page state?
1415 // What else?
1416 frame_entry->set_page_state(params.page_state);
1417
1418 rfh->frame_tree_node()->set_last_committed_frame_entry(frame_entry);
1419
1420 // Reset the frame tree pointers for the last committed entry.
1421 NavigationEntryImpl* last_committed =
1422 NavigationEntryImpl::FromNavigationEntry(GetLastCommittedEntry());
1423 // TODO(creis): Just add this one; don't try to reset the whole tree.
1424 last_committed->ResetFrameTree();
1425 AddFramesToNavigationEntry(last_committed->root_node(),
1426 delegate_->GetFrameTreeRoot());
1427
1297 // We do not need to discard the pending entry in this case, since we will 1428 // We do not need to discard the pending entry in this case, since we will
1298 // not generate commit notifications for this auto-subframe navigation. 1429 // not generate commit notifications for this auto-subframe navigation.
1299 return false; 1430 return false;
1300 } 1431 }
1301 1432
1302 int NavigationControllerImpl::GetIndexOfEntry( 1433 int NavigationControllerImpl::GetIndexOfEntry(
1303 const NavigationEntryImpl* entry) const { 1434 const NavigationEntryImpl* entry) const {
1304 const NavigationEntries::const_iterator i(std::find( 1435 const NavigationEntries::const_iterator i(std::find(
1305 entries_.begin(), 1436 entries_.begin(),
1306 entries_.end(), 1437 entries_.end(),
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1434 void NavigationControllerImpl::PruneAllButLastCommittedInternal() { 1565 void NavigationControllerImpl::PruneAllButLastCommittedInternal() {
1435 // It is up to callers to check the invariants before calling this. 1566 // It is up to callers to check the invariants before calling this.
1436 CHECK(CanPruneAllButLastCommitted()); 1567 CHECK(CanPruneAllButLastCommitted());
1437 1568
1438 // Erase all entries but the last committed entry. There may still be a 1569 // Erase all entries but the last committed entry. There may still be a
1439 // new pending entry after this. 1570 // new pending entry after this.
1440 entries_.erase(entries_.begin(), 1571 entries_.erase(entries_.begin(),
1441 entries_.begin() + last_committed_entry_index_); 1572 entries_.begin() + last_committed_entry_index_);
1442 entries_.erase(entries_.begin() + 1, entries_.end()); 1573 entries_.erase(entries_.begin() + 1, entries_.end());
1443 last_committed_entry_index_ = 0; 1574 last_committed_entry_index_ = 0;
1575 // TODO(creis): Update last committed FNE?.
1444 } 1576 }
1445 1577
1446 void NavigationControllerImpl::ClearAllScreenshots() { 1578 void NavigationControllerImpl::ClearAllScreenshots() {
1447 screenshot_manager_->ClearAllScreenshots(); 1579 screenshot_manager_->ClearAllScreenshots();
1448 } 1580 }
1449 1581
1450 void NavigationControllerImpl::SetSessionStorageNamespace( 1582 void NavigationControllerImpl::SetSessionStorageNamespace(
1451 const std::string& partition_id, 1583 const std::string& partition_id,
1452 SessionStorageNamespace* session_storage_namespace) { 1584 SessionStorageNamespace* session_storage_namespace) {
1453 if (!session_storage_namespace) 1585 if (!session_storage_namespace)
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1556 } 1688 }
1557 1689
1558 NavigationEntryImpl* NavigationControllerImpl::GetPendingEntry() const { 1690 NavigationEntryImpl* NavigationControllerImpl::GetPendingEntry() const {
1559 return pending_entry_; 1691 return pending_entry_;
1560 } 1692 }
1561 1693
1562 int NavigationControllerImpl::GetPendingEntryIndex() const { 1694 int NavigationControllerImpl::GetPendingEntryIndex() const {
1563 return pending_entry_index_; 1695 return pending_entry_index_;
1564 } 1696 }
1565 1697
1566 void NavigationControllerImpl::InsertOrReplaceEntry(NavigationEntryImpl* entry, 1698 void NavigationControllerImpl::InsertOrReplaceEntry(
1567 bool replace) { 1699 RenderFrameHostImpl* rfh,
1700 NavigationEntryImpl* entry,
1701 FrameNavigationEntry* frame_entry,
1702 bool replace) {
1568 DCHECK(entry->GetTransitionType() != ui::PAGE_TRANSITION_AUTO_SUBFRAME); 1703 DCHECK(entry->GetTransitionType() != ui::PAGE_TRANSITION_AUTO_SUBFRAME);
1569 1704
1570 // Copy the pending entry's unique ID to the committed entry. 1705 // Copy the pending entry's unique ID to the committed entry.
1571 // I don't know if pending_entry_index_ can be other than -1 here. 1706 // I don't know if pending_entry_index_ can be other than -1 here.
1572 const NavigationEntryImpl* const pending_entry = 1707 const NavigationEntryImpl* const pending_entry =
1573 (pending_entry_index_ == -1) ? 1708 (pending_entry_index_ == -1) ?
1574 pending_entry_ : entries_[pending_entry_index_].get(); 1709 pending_entry_ : entries_[pending_entry_index_].get();
1575 if (pending_entry) 1710 if (pending_entry)
1576 entry->set_unique_id(pending_entry->GetUniqueID()); 1711 entry->set_unique_id(pending_entry->GetUniqueID());
1577 1712
(...skipping 16 matching lines...) Expand all
1594 num_pruned++; 1729 num_pruned++;
1595 entries_.pop_back(); 1730 entries_.pop_back();
1596 current_size--; 1731 current_size--;
1597 } 1732 }
1598 if (num_pruned > 0) // Only notify if we did prune something. 1733 if (num_pruned > 0) // Only notify if we did prune something.
1599 NotifyPrunedEntries(this, false, num_pruned); 1734 NotifyPrunedEntries(this, false, num_pruned);
1600 } 1735 }
1601 1736
1602 PruneOldestEntryIfFull(); 1737 PruneOldestEntryIfFull();
1603 1738
1739 // New: Set the last committed frame entry for this frame.
1740 // TODO(creis): This breaks in the replace case. We need to update the
1741 // existing FNE with all the data from frame_entry in that case, since many
1742 // NE's might already have references to the existing one.
1743 rfh->frame_tree_node()->set_last_committed_frame_entry(frame_entry);
1744
1745 // New: Give the entry a fresh tree of pointers to the current frame entry for
1746 // each current frame, starting from the root.
1747 // TODO(creis): How can we clear it without deleting the refcounted FNEs?
1748 // I think we want to verify that it's empty here, and have a different way to
1749 // append a new frame to an existing NE.
1750 entry->ResetFrameTree();
1751 AddFramesToNavigationEntry(entry->root_node(), delegate_->GetFrameTreeRoot());
1752
1753 // Finally, add the entry to the joint session history.
1604 entries_.push_back(linked_ptr<NavigationEntryImpl>(entry)); 1754 entries_.push_back(linked_ptr<NavigationEntryImpl>(entry));
1605 last_committed_entry_index_ = static_cast<int>(entries_.size()) - 1; 1755 last_committed_entry_index_ = static_cast<int>(entries_.size()) - 1;
1606 1756
1607 // This is a new page ID, so we need everybody to know about it. 1757 // This is a new page ID, so we need everybody to know about it.
1758 // TODO(creis): Is this still necessary?
1608 delegate_->UpdateMaxPageID(entry->GetPageID()); 1759 delegate_->UpdateMaxPageID(entry->GetPageID());
1609 } 1760 }
1610 1761
1762 void NavigationControllerImpl::AddFramesToNavigationEntry(
1763 NavigationEntryImpl::TreeNode* entry_node,
1764 FrameTreeNode* frame_tree_node) {
1765 // TODO(creis): Remove this once auto-subframe case is fixed. // ?
1766 if (!frame_tree_node->last_committed_frame_entry())
1767 return;
1768
1769 // Put the last committed FrameNavigationEntry for this frame into the
1770 // corresponding spot of the top-level NavigationEntry.
1771 entry_node->SetFrameEntry(frame_tree_node->last_committed_frame_entry());
1772 CHECK(entry_node->frame_entry);
1773
1774 // Repeat for all the child frames.
1775 for (size_t i=0; i < frame_tree_node->child_count(); i++) {
1776 entry_node->children.push_back(
1777 new NavigationEntryImpl::TreeNode(entry_node->entry, nullptr));
1778 CHECK_EQ(i + 1, entry_node->children.size());
1779 AddFramesToNavigationEntry(entry_node->children[i],
1780 frame_tree_node->child_at(i));
1781 }
1782 }
1783
1611 void NavigationControllerImpl::PruneOldestEntryIfFull() { 1784 void NavigationControllerImpl::PruneOldestEntryIfFull() {
1612 if (entries_.size() >= max_entry_count()) { 1785 if (entries_.size() >= max_entry_count()) {
1613 DCHECK_EQ(max_entry_count(), entries_.size()); 1786 DCHECK_EQ(max_entry_count(), entries_.size());
1614 DCHECK_GT(last_committed_entry_index_, 0); 1787 DCHECK_GT(last_committed_entry_index_, 0);
1615 RemoveEntryAtIndex(0); 1788 RemoveEntryAtIndex(0);
1616 NotifyPrunedEntries(this, true, 1); 1789 NotifyPrunedEntries(this, true, 1);
1617 } 1790 }
1618 } 1791 }
1619 1792
1620 void NavigationControllerImpl::NavigateToPendingEntry(ReloadType reload_type) { 1793 void NavigationControllerImpl::NavigateToPendingEntry(ReloadType reload_type) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1654 1827
1655 // For session history navigations only the pending_entry_index_ is set. 1828 // For session history navigations only the pending_entry_index_ is set.
1656 if (!pending_entry_) { 1829 if (!pending_entry_) {
1657 DCHECK_NE(pending_entry_index_, -1); 1830 DCHECK_NE(pending_entry_index_, -1);
1658 pending_entry_ = entries_[pending_entry_index_].get(); 1831 pending_entry_ = entries_[pending_entry_index_].get();
1659 } 1832 }
1660 1833
1661 // This call does not support re-entrancy. See http://crbug.com/347742. 1834 // This call does not support re-entrancy. See http://crbug.com/347742.
1662 CHECK(!in_navigate_to_pending_entry_); 1835 CHECK(!in_navigate_to_pending_entry_);
1663 in_navigate_to_pending_entry_ = true; 1836 in_navigate_to_pending_entry_ = true;
1664 bool success = delegate_->NavigateToPendingEntry(reload_type); 1837 bool success = NavigateToPendingEntryInternal(reload_type);
1665 in_navigate_to_pending_entry_ = false; 1838 in_navigate_to_pending_entry_ = false;
1666 1839
1667 if (!success) 1840 if (!success)
1668 DiscardNonCommittedEntries(); 1841 DiscardNonCommittedEntries();
1669 1842
1670 // If the entry is being restored and doesn't have a SiteInstance yet, fill 1843 // If the entry is being restored and doesn't have a SiteInstance yet, fill
1671 // it in now that we know. This allows us to find the entry when it commits. 1844 // it in now that we know. This allows us to find the entry when it commits.
1672 if (pending_entry_ && !pending_entry_->site_instance() && 1845 if (pending_entry_ && !pending_entry_->site_instance() &&
1673 pending_entry_->restore_type() != NavigationEntryImpl::RESTORE_NONE) { 1846 pending_entry_->restore_type() != NavigationEntryImpl::RESTORE_NONE) {
1674 pending_entry_->set_site_instance(static_cast<SiteInstanceImpl*>( 1847 pending_entry_->set_site_instance(static_cast<SiteInstanceImpl*>(
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1733 } 1906 }
1734 1907
1735 void NavigationControllerImpl::FinishRestore(int selected_index, 1908 void NavigationControllerImpl::FinishRestore(int selected_index,
1736 RestoreType type) { 1909 RestoreType type) {
1737 DCHECK(selected_index >= 0 && selected_index < GetEntryCount()); 1910 DCHECK(selected_index >= 0 && selected_index < GetEntryCount());
1738 ConfigureEntriesForRestore(&entries_, type); 1911 ConfigureEntriesForRestore(&entries_, type);
1739 1912
1740 SetMaxRestoredPageID(static_cast<int32>(GetEntryCount())); 1913 SetMaxRestoredPageID(static_cast<int32>(GetEntryCount()));
1741 1914
1742 last_committed_entry_index_ = selected_index; 1915 last_committed_entry_index_ = selected_index;
1916 // TODO(creis): Update last committed FNE.
1743 } 1917 }
1744 1918
1745 void NavigationControllerImpl::DiscardNonCommittedEntriesInternal() { 1919 void NavigationControllerImpl::DiscardNonCommittedEntriesInternal() {
1746 DiscardPendingEntry(); 1920 DiscardPendingEntry();
1747 DiscardTransientEntry(); 1921 DiscardTransientEntry();
1748 } 1922 }
1749 1923
1750 void NavigationControllerImpl::DiscardPendingEntry() { 1924 void NavigationControllerImpl::DiscardPendingEntry() {
1751 // It is not safe to call DiscardPendingEntry while NavigateToEntry is in 1925 // It is not safe to call DiscardPendingEntry while NavigateToEntry is in
1752 // progress, since this will cause a use-after-free. (We only allow this 1926 // progress, since this will cause a use-after-free. (We only allow this
1753 // when the tab is being destroyed for shutdown, since it won't return to 1927 // when the tab is being destroyed for shutdown, since it won't return to
1754 // NavigateToEntry in that case.) http://crbug.com/347742. 1928 // NavigateToEntry in that case.) http://crbug.com/347742.
1755 CHECK(!in_navigate_to_pending_entry_ || delegate_->IsBeingDestroyed()); 1929 CHECK(!in_navigate_to_pending_entry_ || delegate_->IsBeingDestroyed());
1756 1930
1757 if (pending_entry_index_ == -1) 1931 if (pending_entry_index_ == -1)
1758 delete pending_entry_; 1932 delete pending_entry_;
1759 pending_entry_ = NULL; 1933 pending_entry_ = NULL;
1760 pending_entry_index_ = -1; 1934 pending_entry_index_ = -1;
1761 } 1935 }
1762 1936
1763 void NavigationControllerImpl::DiscardTransientEntry() { 1937 void NavigationControllerImpl::DiscardTransientEntry() {
1764 if (transient_entry_index_ == -1) 1938 if (transient_entry_index_ == -1)
1765 return; 1939 return;
1766 entries_.erase(entries_.begin() + transient_entry_index_); 1940 entries_.erase(entries_.begin() + transient_entry_index_);
1767 if (last_committed_entry_index_ > transient_entry_index_) 1941 if (last_committed_entry_index_ > transient_entry_index_)
1768 last_committed_entry_index_--; 1942 last_committed_entry_index_--;
1769 transient_entry_index_ = -1; 1943 transient_entry_index_ = -1;
1770 } 1944 }
1771 1945
1772 int NavigationControllerImpl::GetEntryIndexWithPageID( 1946 int NavigationControllerImpl::GetEntryIndexWithPageID(int32 page_id) const {
1773 SiteInstance* instance, int32 page_id) const {
1774 for (int i = static_cast<int>(entries_.size()) - 1; i >= 0; --i) { 1947 for (int i = static_cast<int>(entries_.size()) - 1; i >= 0; --i) {
1775 if ((entries_[i]->site_instance() == instance) && 1948 if (entries_[i]->GetPageID() == page_id)
1776 (entries_[i]->GetPageID() == page_id))
1777 return i; 1949 return i;
1778 } 1950 }
1779 return -1; 1951 return -1;
1780 } 1952 }
1781 1953
1782 NavigationEntryImpl* NavigationControllerImpl::GetTransientEntry() const { 1954 NavigationEntryImpl* NavigationControllerImpl::GetTransientEntry() const {
1783 if (transient_entry_index_ == -1) 1955 if (transient_entry_index_ == -1)
1784 return NULL; 1956 return NULL;
1785 return entries_[transient_entry_index_].get(); 1957 return entries_[transient_entry_index_].get();
1786 } 1958 }
(...skipping 27 matching lines...) Expand all
1814 source.entries_[i]->Clone())); 1986 source.entries_[i]->Clone()));
1815 } 1987 }
1816 } 1988 }
1817 } 1989 }
1818 1990
1819 void NavigationControllerImpl::SetGetTimestampCallbackForTest( 1991 void NavigationControllerImpl::SetGetTimestampCallbackForTest(
1820 const base::Callback<base::Time()>& get_timestamp_callback) { 1992 const base::Callback<base::Time()>& get_timestamp_callback) {
1821 get_timestamp_callback_ = get_timestamp_callback; 1993 get_timestamp_callback_ = get_timestamp_callback;
1822 } 1994 }
1823 1995
1996 bool NavigationControllerImpl::NavigateToPendingEntryInternal(
1997 ReloadType reload_type) {
1998 FrameLoadVector same_document_loads;
1999 FrameLoadVector different_document_loads;
2000 DCHECK(pending_entry_);
2001
2002 FrameTreeNode* main_frame = delegate_->GetFrameTreeRoot();
2003 if (GetLastCommittedEntry()) {
2004 RecursiveNavigateToPendingEntry(
2005 main_frame, &same_document_loads, &different_document_loads);
2006 }
2007
2008 if (same_document_loads.empty() && different_document_loads.empty()) {
2009 // If we don't have any frames to navigate at this point, either
2010 // (1) there is no previous history entry to compare against, or
2011 // (2) we were unable to match any frames by name. In the first case,
2012 // doing a different document navigation to the root item is the only valid
2013 // thing to do. In the second case, we should have been able to find a
2014 // frame to navigate based on names if this were a same document
2015 // navigation, so we can safely assume this is the different document case.
2016 // TODO(creis): Is it safe to use a raw pointer for the FNE here?
2017 different_document_loads.push_back(
2018 std::make_pair(main_frame,
2019 pending_entry_->root_node()->frame_entry.get()));
2020 }
2021
2022 // If all the frame loads fail, we will discard the pending entry.
2023 bool success = false;
2024
2025 // Send all the same document frame loads before the different document loads.
2026 for (size_t i = 0; i < same_document_loads.size(); ++i) {
2027 FrameTreeNode* frame = same_document_loads[i].first;
2028 success |= frame->navigator()->NavigateToPendingEntry(
2029 frame, *same_document_loads[i].second, reload_type);
2030 }
2031 for (size_t i = 0; i < different_document_loads.size(); ++i) {
2032 FrameTreeNode* frame = different_document_loads[i].first;
2033 success |= frame->navigator()->NavigateToPendingEntry(
2034 frame, *different_document_loads[i].second, reload_type);
2035 }
2036 return success;
2037 }
2038
2039 void NavigationControllerImpl::RecursiveNavigateToPendingEntry(
2040 FrameTreeNode* frame,
2041 FrameLoadVector* same_document_loads,
2042 FrameLoadVector* different_document_loads) {
2043 DCHECK(pending_entry_);
2044 DCHECK_GE(last_committed_entry_index_, 0);
2045 FrameNavigationEntry* new_item = pending_entry_->GetFrameEntryForFrame(frame);
2046 FrameNavigationEntry* old_item =
2047 GetLastCommittedEntry()->GetFrameEntryForFrame(frame);
2048 if (!new_item)
2049 return;
2050
2051 if (!old_item ||
2052 new_item->item_sequence_number() != old_item->item_sequence_number()) {
2053 if (old_item &&
2054 new_item->document_sequence_number() ==
2055 old_item->document_sequence_number()) {
2056 same_document_loads->push_back(std::make_pair(frame, new_item));
2057 } else {
2058 different_document_loads->push_back(std::make_pair(frame, new_item));
2059 }
2060 return;
2061 }
2062
2063 for (size_t i = 0; i < frame->child_count(); i++) {
2064 RecursiveNavigateToPendingEntry(frame->child_at(i), same_document_loads,
2065 different_document_loads);
2066 }
2067 }
2068
1824 } // namespace content 2069 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698